kern_tame.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. /* $OpenBSD: kern_tame.c,v 1.18 2015/07/29 17:55:27 deraadt Exp $ */
  2. /*
  3. * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
  4. * Copyright (c) 2015 Theo de Raadt <deraadt@openbsd.org>
  5. *
  6. * Permission to use, copy, modify, and distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include <sys/param.h>
  19. #include <sys/types.h>
  20. #include <sys/mount.h>
  21. #include <sys/proc.h>
  22. #include <sys/fcntl.h>
  23. #include <sys/file.h>
  24. #include <sys/filedesc.h>
  25. #include <sys/vnode.h>
  26. #include <sys/mbuf.h>
  27. #include <sys/sysctl.h>
  28. #include <sys/ktrace.h>
  29. #include <sys/ioctl.h>
  30. #include <sys/termios.h>
  31. #include <sys/mtio.h>
  32. #include <net/bpf.h>
  33. #include <net/route.h>
  34. #include <net/if.h>
  35. #include <netinet/in.h>
  36. #include <netinet/tcp.h>
  37. #include <sys/tame.h>
  38. #include <sys/signal.h>
  39. #include <sys/signalvar.h>
  40. #include <sys/syscall.h>
  41. #include <sys/syscallargs.h>
  42. #include <sys/systm.h>
  43. int canonpath(const char *input, char *buf, size_t bufsize);
  44. const u_int tame_syscalls[SYS_MAXSYSCALL] = {
  45. [SYS_exit] = 0xffffffff,
  46. [SYS_kbind] = 0xffffffff,
  47. [SYS_getuid] = _TM_SELF,
  48. [SYS_geteuid] = _TM_SELF,
  49. [SYS_getresuid] = _TM_SELF,
  50. [SYS_getgid] = _TM_SELF,
  51. [SYS_getegid] = _TM_SELF,
  52. [SYS_getresgid] = _TM_SELF,
  53. [SYS_getgroups] = _TM_SELF,
  54. [SYS_getlogin] = _TM_SELF,
  55. [SYS_getpgrp] = _TM_SELF,
  56. [SYS_getpgid] = _TM_SELF,
  57. [SYS_getppid] = _TM_SELF,
  58. [SYS_getsid] = _TM_SELF,
  59. [SYS_getthrid] = _TM_SELF,
  60. [SYS_getrlimit] = _TM_SELF,
  61. [SYS_gettimeofday] = _TM_SELF,
  62. [SYS_getdtablecount] = _TM_SELF,
  63. [SYS_issetugid] = _TM_SELF,
  64. [SYS_clock_getres] = _TM_SELF,
  65. [SYS_clock_gettime] = _TM_SELF,
  66. [SYS_getpid] = _TM_SELF,
  67. [SYS_umask] = _TM_SELF,
  68. [SYS___sysctl] = _TM_SELF, /* read-only; narrow subset */
  69. [SYS_adjtime] = _TM_SELF, /* read-only */
  70. [SYS_chdir] = _TM_RPATH,
  71. [SYS_fchdir] = _TM_SELF, /* careful of directory fd inside jails */
  72. /* needed by threaded programs */
  73. [SYS_sched_yield] = _TM_SELF,
  74. [SYS___thrsleep] = _TM_SELF,
  75. [SYS___thrwakeup] = _TM_SELF,
  76. [SYS___threxit] = _TM_SELF,
  77. [SYS___thrsigdivert] = _TM_SELF,
  78. [SYS_sendsyslog] = _TM_SELF,
  79. [SYS_nanosleep] = _TM_SELF,
  80. [SYS_sigprocmask] = _TM_SELF,
  81. [SYS_sigaction] = _TM_SELF,
  82. [SYS_sigreturn] = _TM_SELF,
  83. [SYS_getitimer] = _TM_SELF,
  84. [SYS_setitimer] = _TM_SELF,
  85. [SYS_tame] = _TM_SELF,
  86. [SYS_wait4] = _TM_SELF,
  87. [SYS_poll] = _TM_RW,
  88. [SYS_kevent] = _TM_RW,
  89. [SYS_kqueue] = _TM_RW,
  90. [SYS_select] = _TM_RW,
  91. [SYS_close] = _TM_RW,
  92. [SYS_dup] = _TM_RW,
  93. [SYS_dup2] = _TM_RW,
  94. [SYS_dup3] = _TM_RW,
  95. [SYS_closefrom] = _TM_RW,
  96. [SYS_shutdown] = _TM_RW,
  97. [SYS_read] = _TM_RW,
  98. [SYS_readv] = _TM_RW,
  99. [SYS_pread] = _TM_RW,
  100. [SYS_preadv] = _TM_RW,
  101. [SYS_write] = _TM_RW,
  102. [SYS_writev] = _TM_RW,
  103. [SYS_pwrite] = _TM_RW,
  104. [SYS_pwritev] = _TM_RW,
  105. [SYS_ftruncate] = _TM_RW,
  106. [SYS_lseek] = _TM_RW,
  107. [SYS_utimes] = _TM_RW,
  108. [SYS_futimes] = _TM_RW,
  109. [SYS_utimensat] = _TM_RW,
  110. [SYS_futimens] = _TM_RW,
  111. [SYS_fcntl] = _TM_RW,
  112. [SYS_fsync] = _TM_RW,
  113. [SYS_pipe] = _TM_RW,
  114. [SYS_pipe2] = _TM_RW,
  115. [SYS_socketpair] = _TM_RW,
  116. [SYS_getdents] = _TM_RW,
  117. [SYS_sendto] = _TM_RW | _TM_DNS_ACTIVE | _TM_YP_ACTIVE,
  118. [SYS_sendmsg] = _TM_RW,
  119. [SYS_recvmsg] = _TM_RW,
  120. [SYS_recvfrom] = _TM_RW | _TM_DNS_ACTIVE | _TM_YP_ACTIVE,
  121. [SYS_fork] = _TM_PROC,
  122. [SYS_vfork] = _TM_PROC,
  123. [SYS_kill] = _TM_PROC,
  124. [SYS_setgroups] = _TM_PROC,
  125. [SYS_setresgid] = _TM_PROC,
  126. [SYS_setresuid] = _TM_PROC,
  127. [SYS_ioctl] = _TM_IOCTL, /* very limited subset */
  128. [SYS_getentropy] = _TM_MALLOC,
  129. [SYS_madvise] = _TM_MALLOC,
  130. [SYS_minherit] = _TM_MALLOC,
  131. [SYS_mmap] = _TM_MALLOC,
  132. [SYS_mprotect] = _TM_MALLOC,
  133. [SYS_mquery] = _TM_MALLOC,
  134. [SYS_munmap] = _TM_MALLOC,
  135. [SYS___getcwd] = _TM_RPATH | _TM_WPATH,
  136. [SYS_open] = _TM_SELF,
  137. [SYS_openat] = _TM_RPATH | _TM_WPATH,
  138. [SYS_stat] = _TM_SELF,
  139. [SYS_fstatat] = _TM_RPATH | _TM_WPATH,
  140. [SYS_access] = _TM_SELF,
  141. [SYS_faccessat] = _TM_RPATH | _TM_WPATH,
  142. [SYS_readlink] = _TM_SELF,
  143. [SYS_readlinkat] = _TM_RPATH | _TM_WPATH,
  144. [SYS_lstat] = _TM_RPATH | _TM_WPATH | _TM_TMPPATH | _TM_DNSPATH,
  145. [SYS_chmod] = _TM_RPATH | _TM_WPATH | _TM_TMPPATH,
  146. [SYS_fchmod] = _TM_RPATH | _TM_WPATH,
  147. [SYS_fchmodat] = _TM_RPATH | _TM_WPATH,
  148. [SYS_chflags] = _TM_RPATH | _TM_WPATH | _TM_TMPPATH,
  149. [SYS_chflagsat] = _TM_RPATH | _TM_WPATH,
  150. [SYS_chown] = _TM_RPATH | _TM_WPATH | _TM_TMPPATH,
  151. [SYS_fchown] = _TM_RPATH | _TM_WPATH,
  152. [SYS_fchownat] = _TM_RPATH | _TM_WPATH,
  153. [SYS_rename] = _TM_CPATH,
  154. [SYS_rmdir] = _TM_CPATH,
  155. [SYS_renameat] = _TM_CPATH,
  156. [SYS_link] = _TM_CPATH,
  157. [SYS_linkat] = _TM_CPATH,
  158. [SYS_symlink] = _TM_CPATH,
  159. [SYS_unlink] = _TM_CPATH | _TM_TMPPATH,
  160. [SYS_unlinkat] = _TM_CPATH,
  161. [SYS_mkdir] = _TM_CPATH,
  162. [SYS_mkdirat] = _TM_CPATH,
  163. [SYS_fstat] = _TM_RW | _TM_RPATH | _TM_WPATH | _TM_TMPPATH, /* rare */
  164. [SYS_socket] = _TM_INET | _TM_UNIX | _TM_DNS_ACTIVE | _TM_YP_ACTIVE,
  165. [SYS_listen] = _TM_INET | _TM_UNIX,
  166. [SYS_bind] = _TM_INET | _TM_UNIX,
  167. [SYS_connect] = _TM_INET | _TM_UNIX | _TM_DNS_ACTIVE | _TM_YP_ACTIVE,
  168. [SYS_accept4] = _TM_INET | _TM_UNIX,
  169. [SYS_accept] = _TM_INET | _TM_UNIX,
  170. [SYS_getpeername] = _TM_INET | _TM_UNIX,
  171. [SYS_getsockname] = _TM_INET | _TM_UNIX,
  172. [SYS_setsockopt] = _TM_INET | _TM_UNIX, /* small subset */
  173. [SYS_getsockopt] = _TM_INET | _TM_UNIX,
  174. [SYS_flock] = _TM_GETPW,
  175. };
  176. int
  177. sys_tame(struct proc *p, void *v, register_t *retval)
  178. {
  179. #if 1
  180. return (ENOSYS);
  181. #else
  182. struct sys_tame_args /* {
  183. syscallarg(int) flags;
  184. } */ *uap = v;
  185. int flags = SCARG(uap, flags);
  186. flags &= _TM_USERSET;
  187. if ((p->p_p->ps_flags & PS_TAMED) == 0) {
  188. p->p_p->ps_flags |= PS_TAMED;
  189. p->p_p->ps_tame = flags;
  190. return (0);
  191. }
  192. /* May not set new bits */
  193. if (((flags | p->p_p->ps_tame) & _TM_USERSET) !=
  194. (p->p_p->ps_tame & _TM_USERSET))
  195. return (EPERM);
  196. /* More tame bits being cleared. Force re-learning of _ACTIVE things */
  197. p->p_p->ps_tame &= flags;
  198. p->p_p->ps_tame &= _TM_USERSET;
  199. return (0);
  200. #endif
  201. }
  202. int
  203. tame_check(struct proc *p, int code)
  204. {
  205. p->p_tamenote = p->p_tameafter = 0; /* XX optimise? */
  206. p->p_tame_syscall = code;
  207. if (code < 0 || code > SYS_MAXSYSCALL - 1)
  208. return (0);
  209. if (p->p_p->ps_tame == 0)
  210. return (code == SYS_exit || code == SYS_kbind);
  211. return (p->p_p->ps_tame & tame_syscalls[code]);
  212. }
  213. int
  214. tame_fail(struct proc *p, int error, int code)
  215. {
  216. printf("tame: pid %d %s syscall %d\n", p->p_pid, p->p_comm,
  217. p->p_tame_syscall);
  218. if (p->p_p->ps_tame & _TM_ABORT) { /* Core dump requested */
  219. struct sigaction sa;
  220. memset(&sa, 0, sizeof sa);
  221. sa.sa_handler = SIG_DFL;
  222. setsigvec(p, SIGABRT, &sa);
  223. psignal(p, SIGABRT);
  224. } else
  225. psignal(p, SIGKILL);
  226. p->p_p->ps_tame = 0; /* Disable all TAME_ flags */
  227. return (error);
  228. }
  229. /*
  230. * Need to make it more obvious that one cannot get through here
  231. * without the right flags set
  232. */
  233. int
  234. tame_namei(struct proc *p, char *origpath)
  235. {
  236. char path[PATH_MAX];
  237. if (p->p_tamenote == TMN_COREDUMP)
  238. return (0); /* Allow a coredump */
  239. if (canonpath(origpath, path, sizeof(path)) != 0)
  240. return (tame_fail(p, EPERM, TAME_RPATH));
  241. /* Detect what looks like a mkstemp(3) family operation */
  242. if ((p->p_p->ps_tame & _TM_TMPPATH) &&
  243. (p->p_tame_syscall == SYS_open) &&
  244. (p->p_tamenote & (TMN_CREAT | TMN_IMODIFY)) == TMN_CREAT &&
  245. strncmp(path, "/tmp/", sizeof("/tmp/") - 1) == 0) {
  246. return (0);
  247. }
  248. /* Allow unlinking of a mkstemp(3) file...
  249. * Good opportunity for strict checks here.
  250. */
  251. if ((p->p_p->ps_tame & _TM_TMPPATH) &&
  252. (p->p_tame_syscall == SYS_unlink) &&
  253. strncmp(path, "/tmp/", sizeof("/tmp") - 1) == 0) {
  254. return (0);
  255. }
  256. /* open, mkdir, or other path creation operation */
  257. if ((p->p_tamenote & (TMN_CREAT | TMN_IMODIFY)) == TMN_CREAT &&
  258. ((p->p_p->ps_tame & _TM_CPATH) == 0))
  259. return (tame_fail(p, EPERM, TAME_CPATH));
  260. /* inode change operation, issued against a path */
  261. if ((p->p_tamenote & (TMN_CREAT | TMN_IMODIFY)) == TMN_IMODIFY &&
  262. ((p->p_p->ps_tame & _TM_CPATH) == 0)) {
  263. // XXX should _TM_CPATH be a seperate check?
  264. return (tame_fail(p, EPERM, TAME_CPATH));
  265. }
  266. if ((p->p_tamenote & TMN_WRITE) &&
  267. (p->p_p->ps_tame & _TM_WPATH) == 0)
  268. return (tame_fail(p, EPERM, TAME_WPATH));
  269. if (p->p_p->ps_tame & _TM_RPATH)
  270. return (0);
  271. if (p->p_p->ps_tame & _TM_WPATH)
  272. return (0);
  273. /* All remaining cases are RPATH */
  274. switch (p->p_tame_syscall) {
  275. case SYS_access:
  276. /* tzset() needs this. */
  277. if (strcmp(path, "/etc/localtime") == 0)
  278. return (0);
  279. break;
  280. case SYS_open:
  281. /* getpw* and friends need a few files */
  282. if (p->p_p->ps_tame & _TM_GETPW) {
  283. if (strcmp(path, "/etc/spwd.db") == 0)
  284. return (0);
  285. if (strcmp(path, "/etc/pwd.db") == 0)
  286. return (0);
  287. if (strcmp(path, "/etc/group") == 0)
  288. return (0);
  289. }
  290. /* DNS needs /etc/{resolv.conf,hosts,services}. */
  291. if (p->p_p->ps_tame & _TM_DNSPATH) {
  292. if (strcmp(path, "/etc/resolv.conf") == 0) {
  293. p->p_tamenote |= TMN_DNSRESOLV;
  294. p->p_tameafter = 1;
  295. return (0);
  296. }
  297. if (strcmp(path, "/etc/hosts") == 0)
  298. return (0);
  299. if (strcmp(path, "/etc/services") == 0)
  300. return (0);
  301. }
  302. if (p->p_p->ps_tame & _TM_GETPW) {
  303. if (strcmp(path, "/var/run/ypbind.lock") == 0) {
  304. p->p_tamenote |= TMN_YPLOCK;
  305. p->p_tameafter = 1;
  306. return (0);
  307. }
  308. if (strncmp(path, "/var/yp/binding/",
  309. sizeof("/var/yp/binding/") - 1) == 0)
  310. return (0);
  311. }
  312. /* tzset() needs these. */
  313. if (strncmp(path, "/usr/share/zoneinfo/",
  314. sizeof("/usr/share/zoneinfo/") - 1) == 0)
  315. return (0);
  316. if (strcmp(path, "/etc/localtime") == 0)
  317. return (0);
  318. /* /usr/share/nls/../libc.cat returns EPERM, for strerror(3). */
  319. if (strncmp(path, "/usr/share/nls/",
  320. sizeof("/usr/share/nls/") - 1) == 0 &&
  321. strcmp(path + strlen(path) - 9, "/libc.cat") == 0)
  322. return (EPERM);
  323. break;
  324. case SYS_readlink:
  325. /* Allow /etc/malloc.conf for malloc(3). */
  326. if (strcmp(path, "/etc/malloc.conf") == 0)
  327. return (0);
  328. break;
  329. case SYS_stat:
  330. /* DNS needs /etc/resolv.conf. */
  331. if (p->p_p->ps_tame & _TM_DNSPATH) {
  332. if (strcmp(path, "/etc/resolv.conf") == 0) {
  333. p->p_tamenote |= TMN_DNSRESOLV;
  334. p->p_tameafter = 1;
  335. return (0);
  336. }
  337. }
  338. break;
  339. }
  340. return (tame_fail(p, EPERM, TAME_RPATH));
  341. }
  342. void
  343. tame_aftersyscall(struct proc *p, int code, int error)
  344. {
  345. if ((p->p_tamenote & TMN_YPLOCK) && error == 0)
  346. atomic_setbits_int(&p->p_p->ps_tame, _TM_YP_ACTIVE | TAME_INET);
  347. if ((p->p_tamenote & TMN_DNSRESOLV) && error == 0)
  348. atomic_setbits_int(&p->p_p->ps_tame, _TM_DNS_ACTIVE);
  349. }
  350. /*
  351. * By default, only the advisory cmsg's can be received from the kernel,
  352. * such as TIMESTAMP ntpd.
  353. *
  354. * If TAME_CMSG is set SCM_RIGHTS is also allowed through for a carefully
  355. * selected set of descriptors (specifically to exclude directories).
  356. *
  357. * This results in a kill upon recv, if some other process on the system
  358. * send a SCM_RIGHTS to an open socket of some sort. That will discourage
  359. * leaving such sockets lying around...
  360. */
  361. int
  362. tame_cmsg_recv(struct proc *p, void *v, int controllen)
  363. {
  364. struct mbuf *control = v;
  365. struct msghdr tmp;
  366. struct cmsghdr *cmsg;
  367. int *fdp, fd;
  368. struct file *fp;
  369. int nfds, i;
  370. if ((p->p_p->ps_flags & PS_TAMED) == 0)
  371. return (0);
  372. /* Scan the cmsg */
  373. memset(&tmp, 0, sizeof(tmp));
  374. tmp.msg_control = mtod(control, struct cmsghdr *);
  375. tmp.msg_controllen = controllen;
  376. cmsg = CMSG_FIRSTHDR(&tmp);
  377. while (cmsg != NULL) {
  378. if (cmsg->cmsg_level == SOL_SOCKET &&
  379. cmsg->cmsg_type == SCM_RIGHTS)
  380. break;
  381. cmsg = CMSG_NXTHDR(&tmp, cmsg);
  382. }
  383. /* No SCM_RIGHTS found -> OK */
  384. if (cmsg == NULL)
  385. return (0);
  386. if ((p->p_p->ps_tame & _TM_CMSG) == 0)
  387. return tame_fail(p, EPERM, TAME_CMSG);
  388. /* In OpenBSD, a CMSG only contains one SCM_RIGHTS. Check it. */
  389. fdp = (int *)CMSG_DATA(cmsg);
  390. nfds = (cmsg->cmsg_len - CMSG_ALIGN(sizeof(*cmsg))) /
  391. sizeof(struct file *);
  392. for (i = 0; i < nfds; i++) {
  393. struct vnode *vp;
  394. fd = *fdp++;
  395. fp = fd_getfile(p->p_fd, fd);
  396. if (fp == NULL)
  397. return tame_fail(p, EBADF, TAME_CMSG);
  398. /* Only allow passing of sockets, pipes, and pure files */
  399. printf("f_type %d\n", fp->f_type);
  400. switch (fp->f_type) {
  401. case DTYPE_SOCKET:
  402. case DTYPE_PIPE:
  403. continue;
  404. case DTYPE_VNODE:
  405. vp = (struct vnode *)fp->f_data;
  406. printf("v_type %d\n", vp->v_type);
  407. if (vp->v_type == VREG)
  408. continue;
  409. break;
  410. default:
  411. break;
  412. }
  413. printf("bad fd type\n");
  414. return tame_fail(p, EPERM, TAME_CMSG);
  415. }
  416. return (0);
  417. }
  418. /*
  419. * When tamed, default prevents sending of a cmsg.
  420. * If CMSG flag is set,
  421. */
  422. int
  423. tame_cmsg_send(struct proc *p, void *v, int controllen)
  424. {
  425. struct mbuf *control = v;
  426. struct msghdr tmp;
  427. struct cmsghdr *cmsg;
  428. int *fdp, fd;
  429. struct file *fp;
  430. int nfds, i;
  431. if ((p->p_p->ps_flags & PS_TAMED) == 0)
  432. return (0);
  433. if ((p->p_p->ps_tame & _TM_CMSG) == 0)
  434. return tame_fail(p, EPERM, TAME_CMSG);
  435. /* Scan the cmsg */
  436. memset(&tmp, 0, sizeof(tmp));
  437. tmp.msg_control = mtod(control, struct cmsghdr *);
  438. tmp.msg_controllen = controllen;
  439. cmsg = CMSG_FIRSTHDR(&tmp);
  440. while (cmsg != NULL) {
  441. if (cmsg->cmsg_level == SOL_SOCKET &&
  442. cmsg->cmsg_type == SCM_RIGHTS)
  443. break;
  444. cmsg = CMSG_NXTHDR(&tmp, cmsg);
  445. }
  446. /* Contains no SCM_RIGHTS, so OK */
  447. if (cmsg == NULL)
  448. return (0);
  449. /* In OpenBSD, a CMSG only contains one SCM_RIGHTS. Check it. */
  450. fdp = (int *)CMSG_DATA(cmsg);
  451. nfds = (cmsg->cmsg_len - CMSG_ALIGN(sizeof(*cmsg))) /
  452. sizeof(struct file *);
  453. for (i = 0; i < nfds; i++) {
  454. struct vnode *vp;
  455. fd = *fdp++;
  456. fp = fd_getfile(p->p_fd, fd);
  457. if (fp == NULL)
  458. return tame_fail(p, EBADF, TAME_CMSG);
  459. /* Only allow passing of sockets, pipes, and pure files */
  460. printf("f_type %d\n", fp->f_type);
  461. switch (fp->f_type) {
  462. case DTYPE_SOCKET:
  463. case DTYPE_PIPE:
  464. continue;
  465. case DTYPE_VNODE:
  466. vp = (struct vnode *)fp->f_data;
  467. printf("v_type %d\n", vp->v_type);
  468. if (vp->v_type == VREG)
  469. continue;
  470. break;
  471. default:
  472. break;
  473. }
  474. /* Not allowed to send a bad fd type */
  475. return tame_fail(p, EPERM, TAME_CMSG);
  476. }
  477. return (0);
  478. }
  479. int
  480. tame_sysctl_check(struct proc *p, int namelen, int *name, void *new)
  481. {
  482. if ((p->p_p->ps_flags & PS_TAMED) == 0)
  483. return (0);
  484. if (new)
  485. return (EFAULT);
  486. /* getifaddrs() */
  487. if ((p->p_p->ps_tame & _TM_INET) &&
  488. namelen == 6 &&
  489. name[0] == CTL_NET && name[1] == PF_ROUTE &&
  490. name[2] == 0 && name[3] == 0 &&
  491. name[4] == NET_RT_IFLIST && name[5] == 0)
  492. return (0);
  493. /* used by arp(8). Exposes MAC addresses known on local nets */
  494. /* XXX Put into a special catagory. */
  495. if ((p->p_p->ps_tame & _TM_INET) &&
  496. namelen == 7 &&
  497. name[0] == CTL_NET && name[1] == PF_ROUTE &&
  498. name[2] == 0 && name[3] == AF_INET &&
  499. name[4] == NET_RT_FLAGS && name[5] == RTF_LLINFO)
  500. return (0);
  501. /* used by ntpd(8) to read sensors. */
  502. /* XXX Put into a special catagory. */
  503. if (namelen >= 3 &&
  504. name[0] == CTL_HW && name[1] == HW_SENSORS)
  505. return (0);
  506. /* getdomainname(), gethostname(), getpagesize(), uname() */
  507. if (namelen == 2 &&
  508. name[0] == CTL_KERN && name[1] == KERN_DOMAINNAME)
  509. return (0);
  510. if (namelen == 2 &&
  511. name[0] == CTL_KERN && name[1] == KERN_HOSTNAME)
  512. return (0);
  513. if (namelen == 2 &&
  514. name[0] == CTL_KERN && name[1] == KERN_OSTYPE)
  515. return (0);
  516. if (namelen == 2 &&
  517. name[0] == CTL_KERN && name[1] == KERN_OSRELEASE)
  518. return (0);
  519. if (namelen == 2 &&
  520. name[0] == CTL_KERN && name[1] == KERN_OSVERSION)
  521. return (0);
  522. if (namelen == 2 &&
  523. name[0] == CTL_KERN && name[1] == KERN_VERSION)
  524. return (0);
  525. if (namelen == 2 &&
  526. name[0] == CTL_HW && name[1] == HW_MACHINE)
  527. return (0);
  528. if (namelen == 2 &&
  529. name[0] == CTL_HW && name[1] == HW_PAGESIZE)
  530. return (0);
  531. printf("tame: pid %d %s sysctl %d: %d %d %d %d %d %d\n",
  532. p->p_pid, p->p_comm, namelen, name[0], name[1],
  533. name[2], name[3], name[4], name[5]);
  534. return (EFAULT);
  535. }
  536. int
  537. tame_adjtime_check(struct proc *p, const void *v)
  538. {
  539. const struct timeval *delta = v;
  540. if ((p->p_p->ps_flags & PS_TAMED) == 0)
  541. return (0);
  542. if (delta)
  543. return (EFAULT);
  544. return (0);
  545. }
  546. int
  547. tame_connect_check(struct proc *p)
  548. {
  549. if ((p->p_p->ps_flags & PS_TAMED) == 0)
  550. return (0);
  551. if ((p->p_p->ps_tame & _TM_DNS_ACTIVE))
  552. return (0); /* A port check happens inside sys_connect() */
  553. if ((p->p_p->ps_tame & (_TM_INET | _TM_UNIX)))
  554. return (0);
  555. return (EPERM);
  556. }
  557. int
  558. tame_recvfrom_check(struct proc *p, void *v)
  559. {
  560. struct sockaddr *from = v;
  561. if ((p->p_p->ps_flags & PS_TAMED) == 0)
  562. return (0);
  563. if ((p->p_p->ps_tame & _TM_DNS_ACTIVE) && from == NULL)
  564. return (0);
  565. if (p->p_p->ps_tame & _TM_INET)
  566. return (0);
  567. if (p->p_p->ps_tame & _TM_UNIX)
  568. return (0);
  569. if (from == NULL)
  570. return (0); /* behaves just like write */
  571. return (EPERM);
  572. }
  573. int
  574. tame_sendto_check(struct proc *p, const void *v)
  575. {
  576. const struct sockaddr *to = v;
  577. if ((p->p_p->ps_flags & PS_TAMED) == 0)
  578. return (0);
  579. if ((p->p_p->ps_tame & _TM_DNS_ACTIVE) && to == NULL)
  580. return (0);
  581. if ((p->p_p->ps_tame & _TM_INET))
  582. return (0);
  583. if ((p->p_p->ps_tame & _TM_UNIX))
  584. return (0);
  585. if (to == NULL)
  586. return (0); /* behaves just like write */
  587. return (EPERM);
  588. }
  589. int
  590. tame_socket_check(struct proc *p, int domain)
  591. {
  592. if ((p->p_p->ps_flags & PS_TAMED) == 0)
  593. return (0);
  594. if ((p->p_p->ps_tame & (_TM_INET | _TM_UNIX)))
  595. return (0);
  596. if ((p->p_p->ps_tame & _TM_DNS_ACTIVE) && domain == AF_INET)
  597. return (0);
  598. return (EPERM);
  599. }
  600. int
  601. tame_bind_check(struct proc *p, const void *v)
  602. {
  603. if ((p->p_p->ps_flags & PS_TAMED) == 0)
  604. return (0);
  605. if ((p->p_p->ps_tame & _TM_INET))
  606. return (0);
  607. return (EPERM);
  608. }
  609. int
  610. tame_ioctl_check(struct proc *p, long com, void *v)
  611. {
  612. struct file *fp = v;
  613. struct vnode *vp = NULL;
  614. if ((p->p_p->ps_flags & PS_TAMED) == 0)
  615. return (0);
  616. if (fp == NULL)
  617. return (EBADF);
  618. vp = (struct vnode *)fp->f_data;
  619. switch (com) {
  620. /*
  621. * This is a set of "get" info ioctls at the top layer. Hopefully
  622. * a safe list, since they are used a lot.
  623. */
  624. case FIOCLEX:
  625. case FIONCLEX:
  626. case FIONREAD:
  627. case FIONBIO:
  628. case FIOGETOWN:
  629. return (0);
  630. case FIOASYNC:
  631. case FIOSETOWN:
  632. return (EPERM);
  633. /* tty subsystem */
  634. case TIOCGWINSZ: /* various programs */
  635. case TIOCSTI: /* ksh? csh? */
  636. if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY))
  637. return (0);
  638. break;
  639. default:
  640. break;
  641. }
  642. if ((p->p_p->ps_tame & _TM_IOCTL) == 0)
  643. return (EPERM);
  644. /*
  645. * Further sets of ioctl become available, but are checked a
  646. * bit more carefully against the vnode.
  647. */
  648. switch (com) {
  649. case BIOCGSTATS: /* bpf: tcpdump privsep on ^C */
  650. if (fp->f_type == DTYPE_VNODE &&
  651. fp->f_ops->fo_ioctl == vn_ioctl)
  652. return (0);
  653. break;
  654. case TIOCSETAF: /* tcsetattr TCSAFLUSH, script */
  655. if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY))
  656. return (0);
  657. break;
  658. case MTIOCGET:
  659. case MTIOCTOP:
  660. /* for pax(1) and such, checking tapes... */
  661. if (fp->f_type == DTYPE_VNODE &&
  662. (vp->v_type == VCHR || vp->v_type == VBLK))
  663. return (0);
  664. break;
  665. case SIOCGIFGROUP:
  666. if ((p->p_p->ps_tame & _TM_INET) &&
  667. fp->f_type == DTYPE_SOCKET)
  668. return (0);
  669. break;
  670. default:
  671. printf("ioctl %lx\n", com);
  672. break;
  673. }
  674. return (EPERM);
  675. }
  676. int
  677. tame_setsockopt_check(struct proc *p, int level, int optname)
  678. {
  679. if ((p->p_p->ps_flags & PS_TAMED) == 0)
  680. return (0);
  681. switch (level) {
  682. case SOL_SOCKET:
  683. switch (optname) {
  684. case SO_RTABLE:
  685. return (EPERM);
  686. }
  687. return (0);
  688. case IPPROTO_TCP:
  689. switch (optname) {
  690. case TCP_NODELAY:
  691. case TCP_MD5SIG:
  692. case TCP_SACK_ENABLE:
  693. case TCP_MAXSEG:
  694. case TCP_NOPUSH:
  695. return (0);
  696. }
  697. case IPPROTO_IP:
  698. switch (optname) {
  699. case IP_TOS:
  700. case IP_TTL:
  701. case IP_MINTTL:
  702. case IP_PORTRANGE:
  703. case IP_RECVDSTADDR:
  704. return (0);
  705. }
  706. case IPPROTO_ICMP:
  707. break;
  708. case IPPROTO_IPV6:
  709. case IPPROTO_ICMPV6:
  710. break;
  711. }
  712. return (EPERM);
  713. }
  714. int
  715. tame_dns_check(struct proc *p, in_port_t port)
  716. {
  717. if ((p->p_p->ps_flags & PS_TAMED) == 0)
  718. return (0);
  719. if ((p->p_p->ps_tame & _TM_INET))
  720. return (0);
  721. if ((p->p_p->ps_tame & _TM_DNS_ACTIVE) && port == htons(53))
  722. return (0); /* Allow a DNS connect outbound */
  723. return (EPERM);
  724. }
  725. int
  726. canonpath(const char *input, char *buf, size_t bufsize)
  727. {
  728. char *p, *q, *s, *end;
  729. /* can't canon relative paths, don't bother */
  730. if (input[0] != '/') {
  731. if (strlcpy(buf, input, bufsize) >= bufsize)
  732. return (EINVAL);
  733. return (0);
  734. }
  735. /* easiest to work with strings always ending in '/' */
  736. if (snprintf(buf, bufsize, "%s/", input) >= bufsize)
  737. return (EINVAL);
  738. /* after this we will only be shortening the string. */
  739. p = buf;
  740. q = p;
  741. while (*p) {
  742. if (p[0] == '/' && p[1] == '/') {
  743. p += 1;
  744. } else if (p[0] == '/' && p[1] == '.' &&
  745. p[2] == '/') {
  746. p += 2;
  747. } else {
  748. *q++ = *p++;
  749. }
  750. }
  751. *q = 0;
  752. end = buf + strlen(buf);
  753. s = buf;
  754. p = s;
  755. while (1) {
  756. /* find "/../" (where's strstr when you need it?) */
  757. while (p < end) {
  758. if (p[0] == '/' && strncmp(p + 1, "../", 3) == 0)
  759. break;
  760. p++;
  761. }
  762. if (p == end)
  763. break;
  764. if (p == s) {
  765. memmove(s, p + 3, end - p - 3 + 1);
  766. end -= 3;
  767. } else {
  768. /* s starts with '/', so we know there's one
  769. * somewhere before p. */
  770. q = p - 1;
  771. while (*q != '/')
  772. q--;
  773. memmove(q, p + 3, end - p - 3 + 1);
  774. end -= p + 3 - q;
  775. p = q;
  776. }
  777. }
  778. if (end > s + 1)
  779. *(end - 1) = 0; /* remove trailing '/' */
  780. return 0;
  781. }