kern_prot.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. /* $OpenBSD: kern_prot.c,v 1.63 2015/03/02 20:46:50 guenther Exp $ */
  2. /* $NetBSD: kern_prot.c,v 1.33 1996/02/09 18:59:42 christos Exp $ */
  3. /*
  4. * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
  5. * The Regents of the University of California. All rights reserved.
  6. * (c) UNIX System Laboratories, Inc.
  7. * All or some portions of this file are derived from material licensed
  8. * to the University of California by American Telephone and Telegraph
  9. * Co. or Unix System Laboratories, Inc. and are reproduced herein with
  10. * the permission of UNIX System Laboratories, Inc.
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions
  14. * are met:
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in the
  19. * documentation and/or other materials provided with the distribution.
  20. * 3. Neither the name of the University nor the names of its contributors
  21. * may be used to endorse or promote products derived from this software
  22. * without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34. * SUCH DAMAGE.
  35. *
  36. * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94
  37. */
  38. /*
  39. * System calls related to processes and protection
  40. */
  41. #include <sys/param.h>
  42. #include <sys/acct.h>
  43. #include <sys/systm.h>
  44. #include <sys/ucred.h>
  45. #include <sys/proc.h>
  46. #include <sys/filedesc.h>
  47. #include <sys/pool.h>
  48. #include <sys/mount.h>
  49. #include <sys/syscallargs.h>
  50. #ifdef __HAVE_MD_TCB
  51. # include <machine/tcb.h>
  52. #endif
  53. inline void
  54. crset(struct ucred *newcr, const struct ucred *cr)
  55. {
  56. KASSERT(cr->cr_ref > 0);
  57. memcpy(
  58. (char *)newcr + offsetof(struct ucred, cr_startcopy),
  59. (const char *)cr + offsetof(struct ucred, cr_startcopy),
  60. sizeof(*cr) - offsetof(struct ucred, cr_startcopy));
  61. }
  62. int
  63. sys_getpid(struct proc *p, void *v, register_t *retval)
  64. {
  65. *retval = p->p_p->ps_pid;
  66. return (0);
  67. }
  68. int
  69. sys_getthrid(struct proc *p, void *v, register_t *retval)
  70. {
  71. *retval = p->p_pid + THREAD_PID_OFFSET;
  72. return (0);
  73. }
  74. int
  75. sys_getppid(struct proc *p, void *v, register_t *retval)
  76. {
  77. *retval = p->p_p->ps_pptr->ps_pid;
  78. return (0);
  79. }
  80. /* Get process group ID; note that POSIX getpgrp takes no parameter */
  81. int
  82. sys_getpgrp(struct proc *p, void *v, register_t *retval)
  83. {
  84. *retval = p->p_p->ps_pgrp->pg_id;
  85. return (0);
  86. }
  87. /*
  88. * SysVR.4 compatible getpgid()
  89. */
  90. int
  91. sys_getpgid(struct proc *curp, void *v, register_t *retval)
  92. {
  93. struct sys_getpgid_args /* {
  94. syscallarg(pid_t) pid;
  95. } */ *uap = v;
  96. struct process *targpr = curp->p_p;
  97. if (SCARG(uap, pid) == 0 || SCARG(uap, pid) == targpr->ps_pid)
  98. goto found;
  99. if ((targpr = prfind(SCARG(uap, pid))) == NULL)
  100. return (ESRCH);
  101. if (targpr->ps_session != curp->p_p->ps_session)
  102. return (EPERM);
  103. found:
  104. *retval = targpr->ps_pgid;
  105. return (0);
  106. }
  107. int
  108. sys_getsid(struct proc *curp, void *v, register_t *retval)
  109. {
  110. struct sys_getsid_args /* {
  111. syscallarg(pid_t) pid;
  112. } */ *uap = v;
  113. struct process *targpr = curp->p_p;
  114. if (SCARG(uap, pid) == 0 || SCARG(uap, pid) == targpr->ps_pid)
  115. goto found;
  116. if ((targpr = prfind(SCARG(uap, pid))) == NULL)
  117. return (ESRCH);
  118. if (targpr->ps_session != curp->p_p->ps_session)
  119. return (EPERM);
  120. found:
  121. /* Skip exiting processes */
  122. if (targpr->ps_pgrp->pg_session->s_leader == NULL)
  123. return (ESRCH);
  124. *retval = targpr->ps_pgrp->pg_session->s_leader->ps_pid;
  125. return (0);
  126. }
  127. int
  128. sys_getuid(struct proc *p, void *v, register_t *retval)
  129. {
  130. *retval = p->p_ucred->cr_ruid;
  131. return (0);
  132. }
  133. int
  134. sys_geteuid(struct proc *p, void *v, register_t *retval)
  135. {
  136. *retval = p->p_ucred->cr_uid;
  137. return (0);
  138. }
  139. int
  140. sys_issetugid(struct proc *p, void *v, register_t *retval)
  141. {
  142. if (p->p_p->ps_flags & PS_SUGIDEXEC)
  143. *retval = 1;
  144. else
  145. *retval = 0;
  146. return (0);
  147. }
  148. int
  149. sys_getgid(struct proc *p, void *v, register_t *retval)
  150. {
  151. *retval = p->p_ucred->cr_rgid;
  152. return (0);
  153. }
  154. /*
  155. * Get effective group ID. The "egid" is groups[0], and could be obtained
  156. * via getgroups. This syscall exists because it is somewhat painful to do
  157. * correctly in a library function.
  158. */
  159. int
  160. sys_getegid(struct proc *p, void *v, register_t *retval)
  161. {
  162. *retval = p->p_ucred->cr_gid;
  163. return (0);
  164. }
  165. int
  166. sys_getgroups(struct proc *p, void *v, register_t *retval)
  167. {
  168. struct sys_getgroups_args /* {
  169. syscallarg(int) gidsetsize;
  170. syscallarg(gid_t *) gidset;
  171. } */ *uap = v;
  172. struct ucred *uc = p->p_ucred;
  173. u_int ngrp;
  174. int error;
  175. if ((ngrp = SCARG(uap, gidsetsize)) == 0) {
  176. *retval = uc->cr_ngroups;
  177. return (0);
  178. }
  179. if (ngrp < uc->cr_ngroups)
  180. return (EINVAL);
  181. ngrp = uc->cr_ngroups;
  182. error = copyout(uc->cr_groups, SCARG(uap, gidset),
  183. ngrp * sizeof(gid_t));
  184. if (error)
  185. return (error);
  186. *retval = ngrp;
  187. return (0);
  188. }
  189. int
  190. sys_setsid(struct proc *p, void *v, register_t *retval)
  191. {
  192. struct session *newsess;
  193. struct pgrp *newpgrp;
  194. struct process *pr = p->p_p;
  195. pid_t pid = pr->ps_pid;
  196. newsess = pool_get(&session_pool, PR_WAITOK);
  197. newpgrp = pool_get(&pgrp_pool, PR_WAITOK);
  198. if (pr->ps_pgid == pid || pgfind(pid)) {
  199. pool_put(&pgrp_pool, newpgrp);
  200. pool_put(&session_pool, newsess);
  201. return (EPERM);
  202. } else {
  203. (void) enterpgrp(pr, pid, newpgrp, newsess);
  204. *retval = pid;
  205. return (0);
  206. }
  207. }
  208. /*
  209. * set process group (setpgid/old setpgrp)
  210. *
  211. * caller does setpgid(targpid, targpgid)
  212. *
  213. * pid must be caller or child of caller (ESRCH)
  214. * if a child
  215. * pid must be in same session (EPERM)
  216. * pid can't have done an exec (EACCES)
  217. * if pgid != pid
  218. * there must exist some pid in same session having pgid (EPERM)
  219. * pid must not be session leader (EPERM)
  220. */
  221. int
  222. sys_setpgid(struct proc *curp, void *v, register_t *retval)
  223. {
  224. struct sys_setpgid_args /* {
  225. syscallarg(pid_t) pid;
  226. syscallarg(pid_t) pgid;
  227. } */ *uap = v;
  228. struct process *curpr = curp->p_p;
  229. struct process *targpr; /* target process */
  230. struct pgrp *pgrp, *newpgrp; /* target pgrp */
  231. pid_t pid, pgid;
  232. int error;
  233. pid = SCARG(uap, pid);
  234. pgid = SCARG(uap, pgid);
  235. if (pgid < 0)
  236. return (EINVAL);
  237. newpgrp = pool_get(&pgrp_pool, PR_WAITOK);
  238. if (pid != 0 && pid != curpr->ps_pid) {
  239. if ((targpr = prfind(pid)) == 0 || !inferior(targpr, curpr)) {
  240. error = ESRCH;
  241. goto out;
  242. }
  243. if (targpr->ps_session != curpr->ps_session) {
  244. error = EPERM;
  245. goto out;
  246. }
  247. if (targpr->ps_flags & PS_EXEC) {
  248. error = EACCES;
  249. goto out;
  250. }
  251. } else
  252. targpr = curpr;
  253. if (SESS_LEADER(targpr)) {
  254. error = EPERM;
  255. goto out;
  256. }
  257. if (pgid == 0)
  258. pgid = targpr->ps_pid;
  259. else if (pgid != targpr->ps_pid)
  260. if ((pgrp = pgfind(pgid)) == 0 ||
  261. pgrp->pg_session != curpr->ps_session) {
  262. error = EPERM;
  263. goto out;
  264. }
  265. return (enterpgrp(targpr, pgid, newpgrp, NULL));
  266. out:
  267. pool_put(&pgrp_pool, newpgrp);
  268. return (error);
  269. }
  270. int
  271. sys_getresuid(struct proc *p, void *v, register_t *retval)
  272. {
  273. struct sys_getresuid_args /* {
  274. syscallarg(uid_t *) ruid;
  275. syscallarg(uid_t *) euid;
  276. syscallarg(uid_t *) suid;
  277. } */ *uap = v;
  278. struct ucred *uc = p->p_ucred;
  279. uid_t *ruid, *euid, *suid;
  280. int error1 = 0, error2 = 0, error3 = 0;
  281. ruid = SCARG(uap, ruid);
  282. euid = SCARG(uap, euid);
  283. suid = SCARG(uap, suid);
  284. if (ruid != NULL)
  285. error1 = copyout(&uc->cr_ruid, ruid, sizeof(*ruid));
  286. if (euid != NULL)
  287. error2 = copyout(&uc->cr_uid, euid, sizeof(*euid));
  288. if (suid != NULL)
  289. error3 = copyout(&uc->cr_svuid, suid, sizeof(*suid));
  290. return (error1 ? error1 : error2 ? error2 : error3);
  291. }
  292. int
  293. sys_setresuid(struct proc *p, void *v, register_t *retval)
  294. {
  295. struct sys_setresuid_args /* {
  296. syscallarg(uid_t) ruid;
  297. syscallarg(uid_t) euid;
  298. syscallarg(uid_t) suid;
  299. } */ *uap = v;
  300. struct process *pr = p->p_p;
  301. struct ucred *pruc, *newcred, *uc = p->p_ucred;
  302. uid_t ruid, euid, suid;
  303. int error;
  304. ruid = SCARG(uap, ruid);
  305. euid = SCARG(uap, euid);
  306. suid = SCARG(uap, suid);
  307. /*
  308. * make permission checks against the thread's ucred,
  309. * but the actual changes will be to the process's ucred
  310. */
  311. pruc = pr->ps_ucred;
  312. if ((ruid == (uid_t)-1 || ruid == pruc->cr_ruid) &&
  313. (euid == (uid_t)-1 || euid == pruc->cr_uid) &&
  314. (suid == (uid_t)-1 || suid == pruc->cr_svuid))
  315. return (0); /* no change */
  316. /*
  317. * Any of the real, effective, and saved uids may be changed
  318. * to the current value of one of the three (root is not limited).
  319. */
  320. if (ruid != (uid_t)-1 &&
  321. ruid != uc->cr_ruid &&
  322. ruid != uc->cr_uid &&
  323. ruid != uc->cr_svuid &&
  324. (error = suser(p, 0)))
  325. return (error);
  326. if (euid != (uid_t)-1 &&
  327. euid != uc->cr_ruid &&
  328. euid != uc->cr_uid &&
  329. euid != uc->cr_svuid &&
  330. (error = suser(p, 0)))
  331. return (error);
  332. if (suid != (uid_t)-1 &&
  333. suid != uc->cr_ruid &&
  334. suid != uc->cr_uid &&
  335. suid != uc->cr_svuid &&
  336. (error = suser(p, 0)))
  337. return (error);
  338. /*
  339. * Copy credentials so other references do not see our changes.
  340. * ps_ucred may change during the crget().
  341. */
  342. newcred = crget();
  343. pruc = pr->ps_ucred;
  344. crset(newcred, pruc);
  345. /*
  346. * Note that unlike the other set*uid() calls, each
  347. * uid type is set independently of the others.
  348. */
  349. if (ruid != (uid_t)-1)
  350. newcred->cr_ruid = ruid;
  351. if (euid != (uid_t)-1)
  352. newcred->cr_uid = euid;
  353. if (suid != (uid_t)-1)
  354. newcred->cr_svuid = suid;
  355. pr->ps_ucred = newcred;
  356. atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
  357. /* now that we can sleep, transfer proc count to new user */
  358. if (ruid != (uid_t)-1 && ruid != pruc->cr_ruid) {
  359. chgproccnt(pruc->cr_ruid, -1);
  360. chgproccnt(ruid, 1);
  361. }
  362. crfree(pruc);
  363. return (0);
  364. }
  365. int
  366. sys_getresgid(struct proc *p, void *v, register_t *retval)
  367. {
  368. struct sys_getresgid_args /* {
  369. syscallarg(gid_t *) rgid;
  370. syscallarg(gid_t *) egid;
  371. syscallarg(gid_t *) sgid;
  372. } */ *uap = v;
  373. struct ucred *uc = p->p_ucred;
  374. gid_t *rgid, *egid, *sgid;
  375. int error1 = 0, error2 = 0, error3 = 0;
  376. rgid = SCARG(uap, rgid);
  377. egid = SCARG(uap, egid);
  378. sgid = SCARG(uap, sgid);
  379. if (rgid != NULL)
  380. error1 = copyout(&uc->cr_rgid, rgid, sizeof(*rgid));
  381. if (egid != NULL)
  382. error2 = copyout(&uc->cr_gid, egid, sizeof(*egid));
  383. if (sgid != NULL)
  384. error3 = copyout(&uc->cr_svgid, sgid, sizeof(*sgid));
  385. return (error1 ? error1 : error2 ? error2 : error3);
  386. }
  387. int
  388. sys_setresgid(struct proc *p, void *v, register_t *retval)
  389. {
  390. struct sys_setresgid_args /* {
  391. syscallarg(gid_t) rgid;
  392. syscallarg(gid_t) egid;
  393. syscallarg(gid_t) sgid;
  394. } */ *uap = v;
  395. struct process *pr = p->p_p;
  396. struct ucred *pruc, *newcred, *uc = p->p_ucred;
  397. gid_t rgid, egid, sgid;
  398. int error;
  399. rgid = SCARG(uap, rgid);
  400. egid = SCARG(uap, egid);
  401. sgid = SCARG(uap, sgid);
  402. /*
  403. * make permission checks against the thread's ucred,
  404. * but the actual changes will be to the process's ucred
  405. */
  406. pruc = pr->ps_ucred;
  407. if ((rgid == (gid_t)-1 || rgid == pruc->cr_rgid) &&
  408. (egid == (gid_t)-1 || egid == pruc->cr_gid) &&
  409. (sgid == (gid_t)-1 || sgid == pruc->cr_svgid))
  410. return (0); /* no change */
  411. /*
  412. * Any of the real, effective, and saved gids may be changed
  413. * to the current value of one of the three (root is not limited).
  414. */
  415. if (rgid != (gid_t)-1 &&
  416. rgid != uc->cr_rgid &&
  417. rgid != uc->cr_gid &&
  418. rgid != uc->cr_svgid &&
  419. (error = suser(p, 0)))
  420. return (error);
  421. if (egid != (gid_t)-1 &&
  422. egid != uc->cr_rgid &&
  423. egid != uc->cr_gid &&
  424. egid != uc->cr_svgid &&
  425. (error = suser(p, 0)))
  426. return (error);
  427. if (sgid != (gid_t)-1 &&
  428. sgid != uc->cr_rgid &&
  429. sgid != uc->cr_gid &&
  430. sgid != uc->cr_svgid &&
  431. (error = suser(p, 0)))
  432. return (error);
  433. /*
  434. * Copy credentials so other references do not see our changes.
  435. * ps_ucred may change during the crget().
  436. */
  437. newcred = crget();
  438. pruc = pr->ps_ucred;
  439. crset(newcred, pruc);
  440. /*
  441. * Note that unlike the other set*gid() calls, each
  442. * gid type is set independently of the others.
  443. */
  444. if (rgid != (gid_t)-1)
  445. newcred->cr_rgid = rgid;
  446. if (egid != (gid_t)-1)
  447. newcred->cr_gid = egid;
  448. if (sgid != (gid_t)-1)
  449. newcred->cr_svgid = sgid;
  450. pr->ps_ucred = newcred;
  451. atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
  452. crfree(pruc);
  453. return (0);
  454. }
  455. int
  456. sys_setregid(struct proc *p, void *v, register_t *retval)
  457. {
  458. struct sys_setregid_args /* {
  459. syscallarg(gid_t) rgid;
  460. syscallarg(gid_t) egid;
  461. } */ *uap = v;
  462. struct process *pr = p->p_p;
  463. struct ucred *pruc, *newcred, *uc = p->p_ucred;
  464. gid_t rgid, egid;
  465. int error;
  466. rgid = SCARG(uap, rgid);
  467. egid = SCARG(uap, egid);
  468. /*
  469. * make permission checks against the thread's ucred,
  470. * but the actual changes will be to the process's ucred
  471. *
  472. * The saved gid check here is complicated: we reset the
  473. * saved gid to the real gid if the real gid is specified
  474. * *and* either it's changing _or_ the saved gid won't equal
  475. * the effective gid. So, the svgid *won't* change when
  476. * the rgid isn't specified or when the rgid isn't changing
  477. * and the svgid equals the requested egid.
  478. */
  479. pruc = pr->ps_ucred;
  480. if ((rgid == (gid_t)-1 || rgid == pruc->cr_rgid) &&
  481. (egid == (gid_t)-1 || egid == pruc->cr_gid) &&
  482. (rgid == (gid_t)-1 || (rgid == pruc->cr_rgid &&
  483. pruc->cr_svgid == (egid != (gid_t)-1 ? egid : pruc->cr_gid))))
  484. return (0); /* no change */
  485. /*
  486. * Any of the real, effective, and saved gids may be changed
  487. * to the current value of one of the three (root is not limited).
  488. */
  489. if (rgid != (gid_t)-1 &&
  490. rgid != uc->cr_rgid &&
  491. rgid != uc->cr_gid &&
  492. rgid != uc->cr_svgid &&
  493. (error = suser(p, 0)))
  494. return (error);
  495. if (egid != (gid_t)-1 &&
  496. egid != uc->cr_rgid &&
  497. egid != uc->cr_gid &&
  498. egid != uc->cr_svgid &&
  499. (error = suser(p, 0)))
  500. return (error);
  501. /*
  502. * Copy credentials so other references do not see our changes.
  503. * ps_ucred may change during the crget().
  504. */
  505. newcred = crget();
  506. pruc = pr->ps_ucred;
  507. crset(newcred, pruc);
  508. if (rgid != (gid_t)-1)
  509. newcred->cr_rgid = rgid;
  510. if (egid != (gid_t)-1)
  511. newcred->cr_gid = egid;
  512. /*
  513. * The saved gid presents a bit of a dilemma, as it did not
  514. * exist when setregid(2) was conceived. We only set the saved
  515. * gid when the real gid is specified and either its value would
  516. * change, or where the saved and effective gids are different.
  517. */
  518. if (rgid != (gid_t)-1 && (rgid != pruc->cr_rgid ||
  519. pruc->cr_svgid != (egid != (gid_t)-1 ? egid : pruc->cr_gid)))
  520. newcred->cr_svgid = rgid;
  521. pr->ps_ucred = newcred;
  522. atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
  523. crfree(pruc);
  524. return (0);
  525. }
  526. int
  527. sys_setreuid(struct proc *p, void *v, register_t *retval)
  528. {
  529. struct sys_setreuid_args /* {
  530. syscallarg(uid_t) ruid;
  531. syscallarg(uid_t) euid;
  532. } */ *uap = v;
  533. struct process *pr = p->p_p;
  534. struct ucred *pruc, *newcred, *uc = p->p_ucred;
  535. uid_t ruid, euid;
  536. int error;
  537. ruid = SCARG(uap, ruid);
  538. euid = SCARG(uap, euid);
  539. /*
  540. * make permission checks against the thread's ucred,
  541. * but the actual changes will be to the process's ucred
  542. *
  543. * The saved uid check here is complicated: we reset the
  544. * saved uid to the real uid if the real uid is specified
  545. * *and* either it's changing _or_ the saved uid won't equal
  546. * the effective uid. So, the svuid *won't* change when
  547. * the ruid isn't specified or when the ruid isn't changing
  548. * and the svuid equals the requested euid.
  549. */
  550. pruc = pr->ps_ucred;
  551. if ((ruid == (uid_t)-1 || ruid == pruc->cr_ruid) &&
  552. (euid == (uid_t)-1 || euid == pruc->cr_uid) &&
  553. (ruid == (uid_t)-1 || (ruid == pruc->cr_ruid &&
  554. pruc->cr_svuid == (euid != (uid_t)-1 ? euid : pruc->cr_uid))))
  555. return (0); /* no change */
  556. /*
  557. * Any of the real, effective, and saved uids may be changed
  558. * to the current value of one of the three (root is not limited).
  559. */
  560. if (ruid != (uid_t)-1 &&
  561. ruid != uc->cr_ruid &&
  562. ruid != uc->cr_uid &&
  563. ruid != uc->cr_svuid &&
  564. (error = suser(p, 0)))
  565. return (error);
  566. if (euid != (uid_t)-1 &&
  567. euid != uc->cr_ruid &&
  568. euid != uc->cr_uid &&
  569. euid != uc->cr_svuid &&
  570. (error = suser(p, 0)))
  571. return (error);
  572. /*
  573. * Copy credentials so other references do not see our changes.
  574. * ps_ucred may change during the crget().
  575. */
  576. newcred = crget();
  577. pruc = pr->ps_ucred;
  578. crset(newcred, pruc);
  579. if (ruid != (uid_t)-1)
  580. newcred->cr_ruid = ruid;
  581. if (euid != (uid_t)-1)
  582. newcred->cr_uid = euid;
  583. /*
  584. * The saved uid presents a bit of a dilemma, as it did not
  585. * exist when setreuid(2) was conceived. We only set the saved
  586. * uid when the real uid is specified and either its value would
  587. * change, or where the saved and effective uids are different.
  588. */
  589. if (ruid != (uid_t)-1 && (ruid != pruc->cr_ruid ||
  590. pruc->cr_svuid != (euid != (uid_t)-1 ? euid : pruc->cr_uid)))
  591. newcred->cr_svuid = ruid;
  592. pr->ps_ucred = newcred;
  593. atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
  594. /* now that we can sleep, transfer proc count to new user */
  595. if (ruid != (uid_t)-1 && ruid != pruc->cr_ruid) {
  596. chgproccnt(pruc->cr_ruid, -1);
  597. chgproccnt(ruid, 1);
  598. }
  599. crfree(pruc);
  600. return (0);
  601. }
  602. int
  603. sys_setuid(struct proc *p, void *v, register_t *retval)
  604. {
  605. struct sys_setuid_args /* {
  606. syscallarg(uid_t) uid;
  607. } */ *uap = v;
  608. struct process *pr = p->p_p;
  609. struct ucred *pruc, *newcred, *uc = p->p_ucred;
  610. uid_t uid;
  611. int did_real, error;
  612. uid = SCARG(uap, uid);
  613. pruc = pr->ps_ucred;
  614. if (pruc->cr_uid == uid &&
  615. pruc->cr_ruid == uid &&
  616. pruc->cr_svuid == uid)
  617. return (0);
  618. if (uid != uc->cr_ruid &&
  619. uid != uc->cr_svuid &&
  620. uid != uc->cr_uid &&
  621. (error = suser(p, 0)))
  622. return (error);
  623. /*
  624. * Copy credentials so other references do not see our changes.
  625. * ps_ucred may change during the crget().
  626. */
  627. newcred = crget();
  628. pruc = pr->ps_ucred;
  629. crset(newcred, pruc);
  630. /*
  631. * Everything's okay, do it.
  632. */
  633. if (uid == pruc->cr_uid || suser(p, 0) == 0) {
  634. did_real = 1;
  635. newcred->cr_ruid = uid;
  636. newcred->cr_svuid = uid;
  637. } else
  638. did_real = 0;
  639. newcred->cr_uid = uid;
  640. pr->ps_ucred = newcred;
  641. atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
  642. /*
  643. * Transfer proc count to new user.
  644. */
  645. if (did_real && uid != pruc->cr_ruid) {
  646. chgproccnt(pruc->cr_ruid, -1);
  647. chgproccnt(uid, 1);
  648. }
  649. crfree(pruc);
  650. return (0);
  651. }
  652. int
  653. sys_seteuid(struct proc *p, void *v, register_t *retval)
  654. {
  655. struct sys_seteuid_args /* {
  656. syscallarg(uid_t) euid;
  657. } */ *uap = v;
  658. struct process *pr = p->p_p;
  659. struct ucred *pruc, *newcred, *uc = p->p_ucred;
  660. uid_t euid;
  661. int error;
  662. euid = SCARG(uap, euid);
  663. if (pr->ps_ucred->cr_uid == euid)
  664. return (0);
  665. if (euid != uc->cr_ruid && euid != uc->cr_svuid &&
  666. (error = suser(p, 0)))
  667. return (error);
  668. /*
  669. * Copy credentials so other references do not see our changes.
  670. * ps_ucred may change during the crget().
  671. */
  672. newcred = crget();
  673. pruc = pr->ps_ucred;
  674. crset(newcred, pruc);
  675. newcred->cr_uid = euid;
  676. pr->ps_ucred = newcred;
  677. atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
  678. crfree(pruc);
  679. return (0);
  680. }
  681. int
  682. sys_setgid(struct proc *p, void *v, register_t *retval)
  683. {
  684. struct sys_setgid_args /* {
  685. syscallarg(gid_t) gid;
  686. } */ *uap = v;
  687. struct process *pr = p->p_p;
  688. struct ucred *pruc, *newcred, *uc = p->p_ucred;
  689. gid_t gid;
  690. int error;
  691. gid = SCARG(uap, gid);
  692. pruc = pr->ps_ucred;
  693. if (pruc->cr_gid == gid &&
  694. pruc->cr_rgid == gid &&
  695. pruc->cr_svgid == gid)
  696. return (0);
  697. if (gid != uc->cr_rgid &&
  698. gid != uc->cr_svgid &&
  699. gid != uc->cr_gid &&
  700. (error = suser(p, 0)))
  701. return (error);
  702. /*
  703. * Copy credentials so other references do not see our changes.
  704. * ps_ucred may change during the crget().
  705. */
  706. newcred = crget();
  707. pruc = pr->ps_ucred;
  708. crset(newcred, pruc);
  709. if (gid == pruc->cr_gid || suser(p, 0) == 0) {
  710. newcred->cr_rgid = gid;
  711. newcred->cr_svgid = gid;
  712. }
  713. newcred->cr_gid = gid;
  714. pr->ps_ucred = newcred;
  715. atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
  716. crfree(pruc);
  717. return (0);
  718. }
  719. int
  720. sys_setegid(struct proc *p, void *v, register_t *retval)
  721. {
  722. struct sys_setegid_args /* {
  723. syscallarg(gid_t) egid;
  724. } */ *uap = v;
  725. struct process *pr = p->p_p;
  726. struct ucred *pruc, *newcred, *uc = p->p_ucred;
  727. gid_t egid;
  728. int error;
  729. egid = SCARG(uap, egid);
  730. if (pr->ps_ucred->cr_gid == egid)
  731. return (0);
  732. if (egid != uc->cr_rgid && egid != uc->cr_svgid &&
  733. (error = suser(p, 0)))
  734. return (error);
  735. /*
  736. * Copy credentials so other references do not see our changes.
  737. * ps_ucred may change during the crget().
  738. */
  739. newcred = crget();
  740. pruc = pr->ps_ucred;
  741. crset(newcred, pruc);
  742. newcred->cr_gid = egid;
  743. pr->ps_ucred = newcred;
  744. atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
  745. crfree(pruc);
  746. return (0);
  747. }
  748. int
  749. sys_setgroups(struct proc *p, void *v, register_t *retval)
  750. {
  751. struct sys_setgroups_args /* {
  752. syscallarg(int) gidsetsize;
  753. syscallarg(const gid_t *) gidset;
  754. } */ *uap = v;
  755. struct process *pr = p->p_p;
  756. struct ucred *pruc, *newcred;
  757. gid_t groups[NGROUPS_MAX];
  758. u_int ngrp;
  759. int error;
  760. if ((error = suser(p, 0)) != 0)
  761. return (error);
  762. ngrp = SCARG(uap, gidsetsize);
  763. if (ngrp > NGROUPS_MAX)
  764. return (EINVAL);
  765. error = copyin(SCARG(uap, gidset), groups, ngrp * sizeof(gid_t));
  766. if (error == 0) {
  767. newcred = crget();
  768. pruc = pr->ps_ucred;
  769. crset(newcred, pruc);
  770. memcpy(newcred->cr_groups, groups, ngrp * sizeof(gid_t));
  771. newcred->cr_ngroups = ngrp;
  772. pr->ps_ucred = newcred;
  773. atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
  774. crfree(pruc);
  775. }
  776. return (error);
  777. }
  778. /*
  779. * Check if gid is a member of the group set.
  780. */
  781. int
  782. groupmember(gid_t gid, struct ucred *cred)
  783. {
  784. gid_t *gp;
  785. gid_t *egp;
  786. if (cred->cr_gid == gid)
  787. return (1);
  788. egp = &(cred->cr_groups[cred->cr_ngroups]);
  789. for (gp = cred->cr_groups; gp < egp; gp++)
  790. if (*gp == gid)
  791. return (1);
  792. return (0);
  793. }
  794. /*
  795. * Test whether this process has special user powers.
  796. * Returns 0 or error.
  797. */
  798. int
  799. suser(struct proc *p, u_int flags)
  800. {
  801. struct ucred *cred = p->p_ucred;
  802. if (cred->cr_uid == 0) {
  803. if (!(flags & SUSER_NOACCT))
  804. p->p_p->ps_acflag |= ASU;
  805. return (0);
  806. }
  807. return (EPERM);
  808. }
  809. /*
  810. * replacement for old suser, for callers who don't have a process
  811. */
  812. int
  813. suser_ucred(struct ucred *cred)
  814. {
  815. if (cred->cr_uid == 0)
  816. return (0);
  817. return (EPERM);
  818. }
  819. /*
  820. * Allocate a zeroed cred structure.
  821. */
  822. struct ucred *
  823. crget(void)
  824. {
  825. struct ucred *cr;
  826. cr = pool_get(&ucred_pool, PR_WAITOK|PR_ZERO);
  827. cr->cr_ref = 1;
  828. return (cr);
  829. }
  830. /*
  831. * Free a cred structure.
  832. * Throws away space when ref count gets to 0.
  833. */
  834. void
  835. crfree(struct ucred *cr)
  836. {
  837. if (--cr->cr_ref == 0)
  838. pool_put(&ucred_pool, cr);
  839. }
  840. /*
  841. * Copy cred structure to a new one and free the old one.
  842. */
  843. struct ucred *
  844. crcopy(struct ucred *cr)
  845. {
  846. struct ucred *newcr;
  847. if (cr->cr_ref == 1)
  848. return (cr);
  849. newcr = crget();
  850. *newcr = *cr;
  851. crfree(cr);
  852. newcr->cr_ref = 1;
  853. return (newcr);
  854. }
  855. /*
  856. * Dup cred struct to a new held one.
  857. */
  858. struct ucred *
  859. crdup(struct ucred *cr)
  860. {
  861. struct ucred *newcr;
  862. newcr = crget();
  863. *newcr = *cr;
  864. newcr->cr_ref = 1;
  865. return (newcr);
  866. }
  867. /*
  868. * Convert the userspace xucred to a kernel ucred
  869. */
  870. int
  871. crfromxucred(struct ucred *cr, const struct xucred *xcr)
  872. {
  873. if (xcr->cr_ngroups < 0 || xcr->cr_ngroups > NGROUPS_MAX)
  874. return (EINVAL);
  875. cr->cr_ref = 1;
  876. cr->cr_uid = xcr->cr_uid;
  877. cr->cr_gid = xcr->cr_gid;
  878. cr->cr_ngroups = xcr->cr_ngroups;
  879. memcpy(cr->cr_groups, xcr->cr_groups,
  880. sizeof(cr->cr_groups[0]) * xcr->cr_ngroups);
  881. return (0);
  882. }
  883. /*
  884. * Get login name, if available.
  885. */
  886. int
  887. sys_getlogin(struct proc *p, void *v, register_t *retval)
  888. {
  889. struct sys_getlogin_args /* {
  890. syscallarg(char *) namebuf;
  891. syscallarg(u_int) namelen;
  892. } */ *uap = v;
  893. struct session *s = p->p_p->ps_pgrp->pg_session;
  894. if (SCARG(uap, namelen) > sizeof(s->s_login))
  895. SCARG(uap, namelen) = sizeof(s->s_login);
  896. return (copyout((caddr_t)s->s_login,
  897. (caddr_t)SCARG(uap, namebuf), SCARG(uap, namelen)));
  898. }
  899. /*
  900. * Set login name.
  901. */
  902. int
  903. sys_setlogin(struct proc *p, void *v, register_t *retval)
  904. {
  905. struct sys_setlogin_args /* {
  906. syscallarg(const char *) namebuf;
  907. } */ *uap = v;
  908. struct session *s = p->p_p->ps_pgrp->pg_session;
  909. int error;
  910. if ((error = suser(p, 0)) != 0)
  911. return (error);
  912. error = copyinstr((caddr_t)SCARG(uap, namebuf), (caddr_t)s->s_login,
  913. sizeof(s->s_login), NULL);
  914. if (error == ENAMETOOLONG)
  915. error = EINVAL;
  916. return (error);
  917. }
  918. /*
  919. * Check if a process is allowed to raise its privileges.
  920. */
  921. int
  922. proc_cansugid(struct proc *p)
  923. {
  924. /* ptrace(2)d processes shouldn't. */
  925. if ((p->p_p->ps_flags & PS_TRACED) != 0)
  926. return (0);
  927. /* processes with shared filedescriptors shouldn't. */
  928. if (p->p_fd->fd_refcnt > 1)
  929. return (0);
  930. /* Allow. */
  931. return (1);
  932. }
  933. /*
  934. * Set address of the proc's thread-control-block
  935. */
  936. int
  937. sys___set_tcb(struct proc *p, void *v, register_t *retval)
  938. {
  939. struct sys___set_tcb_args /* {
  940. syscallarg(void *) tcb;
  941. } */ *uap = v;
  942. TCB_SET(p, SCARG(uap, tcb));
  943. return (0);
  944. }
  945. /*
  946. * Get address of the proc's thread-control-block
  947. */
  948. int
  949. sys___get_tcb(struct proc *p, void *v, register_t *retval)
  950. {
  951. *retval = (register_t)TCB_GET(p);
  952. return (0);
  953. }
  954. /*
  955. * Refresh the thread's reference to the process's credentials
  956. */
  957. void
  958. dorefreshcreds(struct process *pr, struct proc *p)
  959. {
  960. struct ucred *uc = p->p_ucred;
  961. KERNEL_LOCK(); /* XXX should be PROCESS_RLOCK(pr) */
  962. if (uc != pr->ps_ucred) {
  963. p->p_ucred = pr->ps_ucred;
  964. crhold(p->p_ucred);
  965. crfree(uc);
  966. }
  967. KERNEL_UNLOCK();
  968. }