1 1.122 ad /* $NetBSD: kern_prot.c,v 1.122 2020/05/23 23:42:43 ad Exp $ */ 2 1.16 cgd 3 1.14 cgd /* 4 1.15 cgd * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 5 1.15 cgd * The Regents of the University of California. All rights reserved. 6 1.14 cgd * (c) UNIX System Laboratories, Inc. 7 1.14 cgd * All or some portions of this file are derived from material licensed 8 1.14 cgd * to the University of California by American Telephone and Telegraph 9 1.14 cgd * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10 1.14 cgd * the permission of UNIX System Laboratories, Inc. 11 1.14 cgd * 12 1.14 cgd * Redistribution and use in source and binary forms, with or without 13 1.14 cgd * modification, are permitted provided that the following conditions 14 1.14 cgd * are met: 15 1.14 cgd * 1. Redistributions of source code must retain the above copyright 16 1.14 cgd * notice, this list of conditions and the following disclaimer. 17 1.14 cgd * 2. Redistributions in binary form must reproduce the above copyright 18 1.14 cgd * notice, this list of conditions and the following disclaimer in the 19 1.14 cgd * documentation and/or other materials provided with the distribution. 20 1.80 agc * 3. Neither the name of the University nor the names of its contributors 21 1.14 cgd * may be used to endorse or promote products derived from this software 22 1.14 cgd * without specific prior written permission. 23 1.14 cgd * 24 1.14 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 1.14 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 1.14 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 1.14 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 1.14 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 1.14 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 1.14 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 1.14 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 1.14 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 1.14 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 1.14 cgd * SUCH DAMAGE. 35 1.14 cgd * 36 1.44 fvdl * @(#)kern_prot.c 8.9 (Berkeley) 2/14/95 37 1.14 cgd */ 38 1.14 cgd 39 1.14 cgd /* 40 1.14 cgd * System calls related to processes and protection 41 1.14 cgd */ 42 1.65 lukem 43 1.65 lukem #include <sys/cdefs.h> 44 1.122 ad __KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.122 2020/05/23 23:42:43 ad Exp $"); 45 1.45 thorpej 46 1.119 pooka #ifdef _KERNEL_OPT 47 1.51 christos #include "opt_compat_43.h" 48 1.119 pooka #endif 49 1.14 cgd 50 1.14 cgd #include <sys/param.h> 51 1.14 cgd #include <sys/acct.h> 52 1.14 cgd #include <sys/systm.h> 53 1.14 cgd #include <sys/ucred.h> 54 1.14 cgd #include <sys/proc.h> 55 1.14 cgd #include <sys/timeb.h> 56 1.14 cgd #include <sys/times.h> 57 1.82 simonb #include <sys/pool.h> 58 1.102 dsl #include <sys/prot.h> 59 1.72 dsl #include <sys/syslog.h> 60 1.108 pooka #include <sys/uidinfo.h> 61 1.89 elad #include <sys/kauth.h> 62 1.14 cgd 63 1.19 cgd #include <sys/mount.h> 64 1.19 cgd #include <sys/syscallargs.h> 65 1.71 thorpej 66 1.105 dsl int sys_getpid(struct lwp *, const void *, register_t *); 67 1.105 dsl int sys_getpid_with_ppid(struct lwp *, const void *, register_t *); 68 1.105 dsl int sys_getuid(struct lwp *, const void *, register_t *); 69 1.105 dsl int sys_getuid_with_euid(struct lwp *, const void *, register_t *); 70 1.105 dsl int sys_getgid(struct lwp *, const void *, register_t *); 71 1.105 dsl int sys_getgid_with_egid(struct lwp *, const void *, register_t *); 72 1.32 christos 73 1.14 cgd /* ARGSUSED */ 74 1.32 christos int 75 1.105 dsl sys_getpid(struct lwp *l, const void *v, register_t *retval) 76 1.14 cgd { 77 1.70 thorpej struct proc *p = l->l_proc; 78 1.14 cgd 79 1.14 cgd *retval = p->p_pid; 80 1.62 mycroft return (0); 81 1.62 mycroft } 82 1.62 mycroft 83 1.62 mycroft /* ARGSUSED */ 84 1.62 mycroft int 85 1.105 dsl sys_getpid_with_ppid(struct lwp *l, const void *v, register_t *retval) 86 1.62 mycroft { 87 1.70 thorpej struct proc *p = l->l_proc; 88 1.62 mycroft 89 1.62 mycroft retval[0] = p->p_pid; 90 1.121 christos retval[1] = p->p_ppid; 91 1.14 cgd return (0); 92 1.14 cgd } 93 1.14 cgd 94 1.14 cgd /* ARGSUSED */ 95 1.32 christos int 96 1.105 dsl sys_getppid(struct lwp *l, const void *v, register_t *retval) 97 1.14 cgd { 98 1.121 christos struct proc *p = l->l_proc; 99 1.121 christos 100 1.121 christos *retval = p->p_ppid; 101 1.14 cgd return (0); 102 1.14 cgd } 103 1.14 cgd 104 1.14 cgd /* Get process group ID; note that POSIX getpgrp takes no parameter */ 105 1.32 christos int 106 1.105 dsl sys_getpgrp(struct lwp *l, const void *v, register_t *retval) 107 1.14 cgd { 108 1.70 thorpej struct proc *p = l->l_proc; 109 1.14 cgd 110 1.122 ad mutex_enter(&proc_lock); 111 1.14 cgd *retval = p->p_pgrp->pg_id; 112 1.122 ad mutex_exit(&proc_lock); 113 1.14 cgd return (0); 114 1.43 thorpej } 115 1.43 thorpej 116 1.43 thorpej /* 117 1.43 thorpej * Return the process group ID of the session leader (session ID) 118 1.43 thorpej * for the specified process. 119 1.43 thorpej */ 120 1.43 thorpej int 121 1.105 dsl sys_getsid(struct lwp *l, const struct sys_getsid_args *uap, register_t *retval) 122 1.43 thorpej { 123 1.105 dsl /* { 124 1.43 thorpej syscalldarg(pid_t) pid; 125 1.105 dsl } */ 126 1.97 ad pid_t pid = SCARG(uap, pid); 127 1.97 ad struct proc *p; 128 1.97 ad int error = 0; 129 1.97 ad 130 1.122 ad mutex_enter(&proc_lock); 131 1.97 ad if (pid == 0) 132 1.97 ad *retval = l->l_proc->p_session->s_sid; 133 1.110 rmind else if ((p = proc_find(pid)) != NULL) 134 1.97 ad *retval = p->p_session->s_sid; 135 1.97 ad else 136 1.97 ad error = ESRCH; 137 1.122 ad mutex_exit(&proc_lock); 138 1.43 thorpej 139 1.97 ad return error; 140 1.36 mrg } 141 1.36 mrg 142 1.36 mrg int 143 1.105 dsl sys_getpgid(struct lwp *l, const struct sys_getpgid_args *uap, register_t *retval) 144 1.36 mrg { 145 1.105 dsl /* { 146 1.36 mrg syscallarg(pid_t) pid; 147 1.105 dsl } */ 148 1.97 ad pid_t pid = SCARG(uap, pid); 149 1.97 ad struct proc *p; 150 1.97 ad int error = 0; 151 1.97 ad 152 1.122 ad mutex_enter(&proc_lock); 153 1.97 ad if (pid == 0) 154 1.97 ad *retval = l->l_proc->p_pgid; 155 1.110 rmind else if ((p = proc_find(pid)) != NULL) 156 1.97 ad *retval = p->p_pgid; 157 1.97 ad else 158 1.97 ad error = ESRCH; 159 1.122 ad mutex_exit(&proc_lock); 160 1.36 mrg 161 1.97 ad return error; 162 1.14 cgd } 163 1.14 cgd 164 1.14 cgd /* ARGSUSED */ 165 1.32 christos int 166 1.105 dsl sys_getuid(struct lwp *l, const void *v, register_t *retval) 167 1.14 cgd { 168 1.14 cgd 169 1.92 ad *retval = kauth_cred_getuid(l->l_cred); 170 1.62 mycroft return (0); 171 1.62 mycroft } 172 1.62 mycroft 173 1.62 mycroft /* ARGSUSED */ 174 1.62 mycroft int 175 1.105 dsl sys_getuid_with_euid(struct lwp *l, const void *v, register_t *retval) 176 1.62 mycroft { 177 1.62 mycroft 178 1.92 ad retval[0] = kauth_cred_getuid(l->l_cred); 179 1.92 ad retval[1] = kauth_cred_geteuid(l->l_cred); 180 1.14 cgd return (0); 181 1.14 cgd } 182 1.14 cgd 183 1.14 cgd /* ARGSUSED */ 184 1.32 christos int 185 1.105 dsl sys_geteuid(struct lwp *l, const void *v, register_t *retval) 186 1.14 cgd { 187 1.14 cgd 188 1.92 ad *retval = kauth_cred_geteuid(l->l_cred); 189 1.14 cgd return (0); 190 1.14 cgd } 191 1.14 cgd 192 1.14 cgd /* ARGSUSED */ 193 1.32 christos int 194 1.105 dsl sys_getgid(struct lwp *l, const void *v, register_t *retval) 195 1.14 cgd { 196 1.14 cgd 197 1.92 ad *retval = kauth_cred_getgid(l->l_cred); 198 1.62 mycroft return (0); 199 1.62 mycroft } 200 1.62 mycroft 201 1.62 mycroft /* ARGSUSED */ 202 1.62 mycroft int 203 1.105 dsl sys_getgid_with_egid(struct lwp *l, const void *v, register_t *retval) 204 1.62 mycroft { 205 1.62 mycroft 206 1.92 ad retval[0] = kauth_cred_getgid(l->l_cred); 207 1.92 ad retval[1] = kauth_cred_getegid(l->l_cred); 208 1.14 cgd return (0); 209 1.14 cgd } 210 1.14 cgd 211 1.14 cgd /* 212 1.14 cgd * Get effective group ID. The "egid" is groups[0], and could be obtained 213 1.14 cgd * via getgroups. This syscall exists because it is somewhat painful to do 214 1.14 cgd * correctly in a library function. 215 1.14 cgd */ 216 1.14 cgd /* ARGSUSED */ 217 1.32 christos int 218 1.105 dsl sys_getegid(struct lwp *l, const void *v, register_t *retval) 219 1.14 cgd { 220 1.75 enami 221 1.92 ad *retval = kauth_cred_getegid(l->l_cred); 222 1.14 cgd return (0); 223 1.14 cgd } 224 1.14 cgd 225 1.32 christos int 226 1.105 dsl sys_getgroups(struct lwp *l, const struct sys_getgroups_args *uap, register_t *retval) 227 1.29 thorpej { 228 1.105 dsl /* { 229 1.41 thorpej syscallarg(int) gidsetsize; 230 1.19 cgd syscallarg(gid_t *) gidset; 231 1.105 dsl } */ 232 1.102 dsl 233 1.102 dsl *retval = kauth_cred_ngroups(l->l_cred); 234 1.102 dsl if (SCARG(uap, gidsetsize) == 0) 235 1.102 dsl return 0; 236 1.113 martin if (SCARG(uap, gidsetsize) < (int)*retval) 237 1.102 dsl return EINVAL; 238 1.14 cgd 239 1.103 dsl return kauth_cred_getgroups(l->l_cred, SCARG(uap, gidset), *retval, 240 1.103 dsl UIO_USERSPACE); 241 1.14 cgd } 242 1.14 cgd 243 1.32 christos int 244 1.105 dsl sys_setsid(struct lwp *l, const void *v, register_t *retval) 245 1.14 cgd { 246 1.70 thorpej struct proc *p = l->l_proc; 247 1.97 ad int error; 248 1.14 cgd 249 1.109 rmind error = proc_enterpgrp(p, p->p_pid, p->p_pid, true); 250 1.97 ad *retval = p->p_pid; 251 1.97 ad return (error); 252 1.14 cgd } 253 1.14 cgd 254 1.97 ad 255 1.14 cgd /* 256 1.14 cgd * set process group (setpgid/old setpgrp) 257 1.14 cgd * 258 1.14 cgd * caller does setpgid(targpid, targpgid) 259 1.14 cgd * 260 1.39 mikel * pgid must be in valid range (EINVAL) 261 1.14 cgd * pid must be caller or child of caller (ESRCH) 262 1.14 cgd * if a child 263 1.14 cgd * pid must be in same session (EPERM) 264 1.14 cgd * pid can't have done an exec (EACCES) 265 1.14 cgd * if pgid != pid 266 1.14 cgd * there must exist some pid in same session having pgid (EPERM) 267 1.14 cgd * pid must not be session leader (EPERM) 268 1.77 dsl * 269 1.109 rmind * Permission checks now in proc_enterpgrp() 270 1.14 cgd */ 271 1.32 christos int 272 1.109 rmind sys_setpgid(struct lwp *l, const struct sys_setpgid_args *uap, 273 1.109 rmind register_t *retval) 274 1.29 thorpej { 275 1.105 dsl /* { 276 1.19 cgd syscallarg(int) pid; 277 1.19 cgd syscallarg(int) pgid; 278 1.105 dsl } */ 279 1.97 ad struct proc *p = l->l_proc; 280 1.97 ad pid_t targp, pgid; 281 1.14 cgd 282 1.39 mikel if (SCARG(uap, pgid) < 0) 283 1.77 dsl return EINVAL; 284 1.97 ad if ((targp = SCARG(uap, pid)) == 0) 285 1.97 ad targp = p->p_pid; 286 1.97 ad if ((pgid = SCARG(uap, pgid)) == 0) 287 1.97 ad pgid = targp; 288 1.14 cgd 289 1.109 rmind return proc_enterpgrp(p, targp, pgid, false); 290 1.14 cgd } 291 1.14 cgd 292 1.76 dsl /* 293 1.76 dsl * Set real, effective and saved uids to the requested values. 294 1.76 dsl * non-root callers can only ever change uids to values that match 295 1.76 dsl * one of the processes current uid values. 296 1.76 dsl * This is further restricted by the flags argument. 297 1.76 dsl */ 298 1.76 dsl 299 1.76 dsl int 300 1.76 dsl do_setresuid(struct lwp *l, uid_t r, uid_t e, uid_t sv, u_int flags) 301 1.76 dsl { 302 1.93 ad struct proc *p = l->l_proc; 303 1.97 ad kauth_cred_t cred, ncred; 304 1.97 ad 305 1.97 ad ncred = kauth_cred_alloc(); 306 1.93 ad 307 1.93 ad /* Get a write lock on the process credential. */ 308 1.97 ad proc_crmod_enter(); 309 1.93 ad cred = p->p_cred; 310 1.76 dsl 311 1.90 yamt /* 312 1.93 ad * Check that the new value is one of the allowed existing values, 313 1.93 ad * or that we have root privilege. 314 1.90 yamt */ 315 1.90 yamt if ((r != -1 316 1.90 yamt && !((flags & ID_R_EQ_R) && r == kauth_cred_getuid(cred)) 317 1.90 yamt && !((flags & ID_R_EQ_E) && r == kauth_cred_geteuid(cred)) 318 1.90 yamt && !((flags & ID_R_EQ_S) && r == kauth_cred_getsvuid(cred))) || 319 1.90 yamt (e != -1 320 1.90 yamt && !((flags & ID_E_EQ_R) && e == kauth_cred_getuid(cred)) 321 1.90 yamt && !((flags & ID_E_EQ_E) && e == kauth_cred_geteuid(cred)) 322 1.90 yamt && !((flags & ID_E_EQ_S) && e == kauth_cred_getsvuid(cred))) || 323 1.90 yamt (sv != -1 324 1.90 yamt && !((flags & ID_S_EQ_R) && sv == kauth_cred_getuid(cred)) 325 1.90 yamt && !((flags & ID_S_EQ_E) && sv == kauth_cred_geteuid(cred)) 326 1.90 yamt && !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvuid(cred)))) { 327 1.90 yamt int error; 328 1.90 yamt 329 1.94 elad error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID, 330 1.94 elad p, NULL, NULL, NULL); 331 1.90 yamt if (error != 0) { 332 1.99 thorpej proc_crmod_leave(cred, ncred, false); 333 1.76 dsl return error; 334 1.90 yamt } 335 1.76 dsl } 336 1.76 dsl 337 1.76 dsl /* If nothing has changed, short circuit the request */ 338 1.89 elad if ((r == -1 || r == kauth_cred_getuid(cred)) 339 1.89 elad && (e == -1 || e == kauth_cred_geteuid(cred)) 340 1.90 yamt && (sv == -1 || sv == kauth_cred_getsvuid(cred))) { 341 1.99 thorpej proc_crmod_leave(cred, ncred, false); 342 1.76 dsl return 0; 343 1.90 yamt } 344 1.76 dsl 345 1.97 ad kauth_cred_clone(cred, ncred); 346 1.91 ad 347 1.97 ad if (r != -1 && r != kauth_cred_getuid(ncred)) { 348 1.117 rmind u_long nlwps; 349 1.117 rmind 350 1.117 rmind /* Update count of processes for this user. */ 351 1.97 ad (void)chgproccnt(kauth_cred_getuid(ncred), -1); 352 1.76 dsl (void)chgproccnt(r, 1); 353 1.115 christos 354 1.117 rmind /* The first LWP of a process is excluded. */ 355 1.117 rmind KASSERT(mutex_owned(p->p_lock)); 356 1.117 rmind nlwps = p->p_nlwps - 1; 357 1.116 christos (void)chglwpcnt(kauth_cred_getuid(ncred), -nlwps); 358 1.115 christos (void)chglwpcnt(r, nlwps); 359 1.115 christos 360 1.97 ad kauth_cred_setuid(ncred, r); 361 1.76 dsl } 362 1.76 dsl if (sv != -1) 363 1.97 ad kauth_cred_setsvuid(ncred, sv); 364 1.91 ad if (e != -1) 365 1.97 ad kauth_cred_seteuid(ncred, e); 366 1.93 ad 367 1.92 ad /* Broadcast our credentials to the process and other LWPs. */ 368 1.99 thorpej proc_crmod_leave(ncred, cred, true); 369 1.92 ad 370 1.76 dsl return 0; 371 1.76 dsl } 372 1.76 dsl 373 1.76 dsl /* 374 1.76 dsl * Set real, effective and saved gids to the requested values. 375 1.76 dsl * non-root callers can only ever change gids to values that match 376 1.76 dsl * one of the processes current gid values. 377 1.76 dsl * This is further restricted by the flags argument. 378 1.76 dsl */ 379 1.76 dsl 380 1.76 dsl int 381 1.76 dsl do_setresgid(struct lwp *l, gid_t r, gid_t e, gid_t sv, u_int flags) 382 1.76 dsl { 383 1.93 ad struct proc *p = l->l_proc; 384 1.97 ad kauth_cred_t cred, ncred; 385 1.97 ad 386 1.97 ad ncred = kauth_cred_alloc(); 387 1.93 ad 388 1.93 ad /* Get a write lock on the process credential. */ 389 1.97 ad proc_crmod_enter(); 390 1.93 ad cred = p->p_cred; 391 1.76 dsl 392 1.90 yamt /* 393 1.90 yamt * check new value is one of the allowed existing values. 394 1.90 yamt * otherwise, check if we have root privilege. 395 1.90 yamt */ 396 1.90 yamt if ((r != -1 397 1.90 yamt && !((flags & ID_R_EQ_R) && r == kauth_cred_getgid(cred)) 398 1.90 yamt && !((flags & ID_R_EQ_E) && r == kauth_cred_getegid(cred)) 399 1.90 yamt && !((flags & ID_R_EQ_S) && r == kauth_cred_getsvgid(cred))) || 400 1.90 yamt (e != -1 401 1.90 yamt && !((flags & ID_E_EQ_R) && e == kauth_cred_getgid(cred)) 402 1.90 yamt && !((flags & ID_E_EQ_E) && e == kauth_cred_getegid(cred)) 403 1.90 yamt && !((flags & ID_E_EQ_S) && e == kauth_cred_getsvgid(cred))) || 404 1.90 yamt (sv != -1 405 1.90 yamt && !((flags & ID_S_EQ_R) && sv == kauth_cred_getgid(cred)) 406 1.90 yamt && !((flags & ID_S_EQ_E) && sv == kauth_cred_getegid(cred)) 407 1.90 yamt && !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvgid(cred)))) { 408 1.90 yamt int error; 409 1.90 yamt 410 1.94 elad error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID, 411 1.94 elad p, NULL, NULL, NULL); 412 1.90 yamt if (error != 0) { 413 1.99 thorpej proc_crmod_leave(cred, ncred, false); 414 1.76 dsl return error; 415 1.90 yamt } 416 1.76 dsl } 417 1.76 dsl 418 1.76 dsl /* If nothing has changed, short circuit the request */ 419 1.89 elad if ((r == -1 || r == kauth_cred_getgid(cred)) 420 1.89 elad && (e == -1 || e == kauth_cred_getegid(cred)) 421 1.90 yamt && (sv == -1 || sv == kauth_cred_getsvgid(cred))) { 422 1.99 thorpej proc_crmod_leave(cred, ncred, false); 423 1.76 dsl return 0; 424 1.90 yamt } 425 1.76 dsl 426 1.97 ad kauth_cred_clone(cred, ncred); 427 1.91 ad 428 1.76 dsl if (r != -1) 429 1.97 ad kauth_cred_setgid(ncred, r); 430 1.76 dsl if (sv != -1) 431 1.97 ad kauth_cred_setsvgid(ncred, sv); 432 1.91 ad if (e != -1) 433 1.97 ad kauth_cred_setegid(ncred, e); 434 1.93 ad 435 1.92 ad /* Broadcast our credentials to the process and other LWPs. */ 436 1.99 thorpej proc_crmod_leave(ncred, cred, true); 437 1.92 ad 438 1.76 dsl return 0; 439 1.76 dsl } 440 1.76 dsl 441 1.14 cgd /* ARGSUSED */ 442 1.32 christos int 443 1.105 dsl sys_setuid(struct lwp *l, const struct sys_setuid_args *uap, register_t *retval) 444 1.29 thorpej { 445 1.105 dsl /* { 446 1.19 cgd syscallarg(uid_t) uid; 447 1.105 dsl } */ 448 1.76 dsl uid_t uid = SCARG(uap, uid); 449 1.14 cgd 450 1.76 dsl return do_setresuid(l, uid, uid, uid, 451 1.76 dsl ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R); 452 1.14 cgd } 453 1.14 cgd 454 1.14 cgd /* ARGSUSED */ 455 1.32 christos int 456 1.105 dsl sys_seteuid(struct lwp *l, const struct sys_seteuid_args *uap, register_t *retval) 457 1.29 thorpej { 458 1.105 dsl /* { 459 1.19 cgd syscallarg(uid_t) euid; 460 1.105 dsl } */ 461 1.59 christos 462 1.76 dsl return do_setresuid(l, -1, SCARG(uap, euid), -1, ID_E_EQ_R | ID_E_EQ_S); 463 1.14 cgd } 464 1.14 cgd 465 1.35 mycroft int 466 1.105 dsl sys_setreuid(struct lwp *l, const struct sys_setreuid_args *uap, register_t *retval) 467 1.35 mycroft { 468 1.105 dsl /* { 469 1.35 mycroft syscallarg(uid_t) ruid; 470 1.35 mycroft syscallarg(uid_t) euid; 471 1.105 dsl } */ 472 1.92 ad kauth_cred_t cred = l->l_cred; 473 1.76 dsl uid_t ruid, euid, svuid; 474 1.35 mycroft 475 1.35 mycroft ruid = SCARG(uap, ruid); 476 1.35 mycroft euid = SCARG(uap, euid); 477 1.92 ad 478 1.76 dsl if (ruid == -1) 479 1.92 ad ruid = kauth_cred_getuid(cred); 480 1.76 dsl if (euid == -1) 481 1.92 ad euid = kauth_cred_geteuid(cred); 482 1.92 ad 483 1.76 dsl /* Saved uid is set to the new euid if the ruid changed */ 484 1.92 ad svuid = (ruid == kauth_cred_getuid(cred)) ? -1 : euid; 485 1.76 dsl 486 1.76 dsl return do_setresuid(l, ruid, euid, svuid, 487 1.76 dsl ID_R_EQ_R | ID_R_EQ_E | 488 1.76 dsl ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S | 489 1.76 dsl ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S); 490 1.35 mycroft } 491 1.35 mycroft 492 1.14 cgd /* ARGSUSED */ 493 1.32 christos int 494 1.105 dsl sys_setgid(struct lwp *l, const struct sys_setgid_args *uap, register_t *retval) 495 1.29 thorpej { 496 1.105 dsl /* { 497 1.19 cgd syscallarg(gid_t) gid; 498 1.105 dsl } */ 499 1.76 dsl gid_t gid = SCARG(uap, gid); 500 1.14 cgd 501 1.76 dsl return do_setresgid(l, gid, gid, gid, 502 1.76 dsl ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R); 503 1.14 cgd } 504 1.14 cgd 505 1.14 cgd /* ARGSUSED */ 506 1.32 christos int 507 1.105 dsl sys_setegid(struct lwp *l, const struct sys_setegid_args *uap, register_t *retval) 508 1.29 thorpej { 509 1.105 dsl /* { 510 1.19 cgd syscallarg(gid_t) egid; 511 1.105 dsl } */ 512 1.14 cgd 513 1.76 dsl return do_setresgid(l, -1, SCARG(uap, egid), -1, ID_E_EQ_R | ID_E_EQ_S); 514 1.35 mycroft } 515 1.35 mycroft 516 1.35 mycroft int 517 1.105 dsl sys_setregid(struct lwp *l, const struct sys_setregid_args *uap, register_t *retval) 518 1.35 mycroft { 519 1.105 dsl /* { 520 1.35 mycroft syscallarg(gid_t) rgid; 521 1.35 mycroft syscallarg(gid_t) egid; 522 1.105 dsl } */ 523 1.92 ad kauth_cred_t cred = l->l_cred; 524 1.76 dsl gid_t rgid, egid, svgid; 525 1.35 mycroft 526 1.35 mycroft rgid = SCARG(uap, rgid); 527 1.35 mycroft egid = SCARG(uap, egid); 528 1.92 ad 529 1.76 dsl if (rgid == -1) 530 1.92 ad rgid = kauth_cred_getgid(cred); 531 1.76 dsl if (egid == -1) 532 1.92 ad egid = kauth_cred_getegid(cred); 533 1.92 ad 534 1.76 dsl /* Saved gid is set to the new egid if the rgid changed */ 535 1.92 ad svgid = rgid == kauth_cred_getgid(cred) ? -1 : egid; 536 1.76 dsl 537 1.76 dsl return do_setresgid(l, rgid, egid, svgid, 538 1.76 dsl ID_R_EQ_R | ID_R_EQ_E | 539 1.76 dsl ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S | 540 1.76 dsl ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S); 541 1.57 minoura } 542 1.57 minoura 543 1.57 minoura int 544 1.105 dsl sys_issetugid(struct lwp *l, const void *v, register_t *retval) 545 1.57 minoura { 546 1.70 thorpej struct proc *p = l->l_proc; 547 1.75 enami 548 1.57 minoura /* 549 1.57 minoura * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 550 1.98 pavel * we use PK_SUGID because we consider changing the owners as 551 1.57 minoura * "tainting" as well. 552 1.57 minoura * This is significant for procs that start as root and "become" 553 1.57 minoura * a user without an exec - programs cannot know *everything* 554 1.57 minoura * that libc *might* have put in their data segment. 555 1.57 minoura */ 556 1.98 pavel *retval = (p->p_flag & PK_SUGID) != 0; 557 1.60 christos return (0); 558 1.14 cgd } 559 1.14 cgd 560 1.15 cgd /* ARGSUSED */ 561 1.32 christos int 562 1.105 dsl sys_setgroups(struct lwp *l, const struct sys_setgroups_args *uap, register_t *retval) 563 1.29 thorpej { 564 1.105 dsl /* { 565 1.41 thorpej syscallarg(int) gidsetsize; 566 1.38 cgd syscallarg(const gid_t *) gidset; 567 1.105 dsl } */ 568 1.102 dsl kauth_cred_t ncred; 569 1.15 cgd int error; 570 1.15 cgd 571 1.102 dsl ncred = kauth_cred_alloc(); 572 1.103 dsl error = kauth_cred_setgroups(ncred, SCARG(uap, gidset), 573 1.103 dsl SCARG(uap, gidsetsize), -1, UIO_USERSPACE); 574 1.102 dsl if (error != 0) { 575 1.102 dsl kauth_cred_free(ncred); 576 1.97 ad return error; 577 1.102 dsl } 578 1.97 ad 579 1.102 dsl return kauth_proc_setgroups(l, ncred); 580 1.14 cgd } 581 1.14 cgd 582 1.14 cgd /* 583 1.14 cgd * Get login name, if available. 584 1.14 cgd */ 585 1.14 cgd /* ARGSUSED */ 586 1.32 christos int 587 1.105 dsl sys___getlogin(struct lwp *l, const struct sys___getlogin_args *uap, register_t *retval) 588 1.29 thorpej { 589 1.105 dsl /* { 590 1.19 cgd syscallarg(char *) namebuf; 591 1.53 kleink syscallarg(size_t) namelen; 592 1.105 dsl } */ 593 1.70 thorpej struct proc *p = l->l_proc; 594 1.97 ad char login[sizeof(p->p_session->s_login)]; 595 1.118 maxv size_t namelen = SCARG(uap, namelen); 596 1.14 cgd 597 1.97 ad if (namelen > sizeof(login)) 598 1.97 ad namelen = sizeof(login); 599 1.122 ad mutex_enter(&proc_lock); 600 1.97 ad memcpy(login, p->p_session->s_login, namelen); 601 1.122 ad mutex_exit(&proc_lock); 602 1.97 ad return (copyout(login, (void *)SCARG(uap, namebuf), namelen)); 603 1.14 cgd } 604 1.14 cgd 605 1.14 cgd /* 606 1.14 cgd * Set login name. 607 1.14 cgd */ 608 1.14 cgd /* ARGSUSED */ 609 1.32 christos int 610 1.105 dsl sys___setlogin(struct lwp *l, const struct sys___setlogin_args *uap, register_t *retval) 611 1.29 thorpej { 612 1.105 dsl /* { 613 1.38 cgd syscallarg(const char *) namebuf; 614 1.105 dsl } */ 615 1.70 thorpej struct proc *p = l->l_proc; 616 1.97 ad struct session *sp; 617 1.97 ad char newname[sizeof sp->s_login + 1]; 618 1.14 cgd int error; 619 1.14 cgd 620 1.94 elad if ((error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_SETID, 621 1.94 elad p, NULL, NULL, NULL)) != 0) 622 1.14 cgd return (error); 623 1.114 matt error = copyinstr(SCARG(uap, namebuf), newname, sizeof newname, NULL); 624 1.72 dsl if (error != 0) 625 1.75 enami return (error == ENAMETOOLONG ? EINVAL : error); 626 1.72 dsl 627 1.122 ad mutex_enter(&proc_lock); 628 1.97 ad sp = p->p_session; 629 1.97 ad if (sp->s_flags & S_LOGIN_SET && p->p_pid != sp->s_sid && 630 1.97 ad strncmp(newname, sp->s_login, sizeof sp->s_login) != 0) 631 1.74 wiz log(LOG_WARNING, "%s (pid %d) changing logname from " 632 1.74 wiz "%.*s to %s\n", p->p_comm, p->p_pid, 633 1.97 ad (int)sizeof sp->s_login, sp->s_login, newname); 634 1.97 ad sp->s_flags |= S_LOGIN_SET; 635 1.97 ad strncpy(sp->s_login, newname, sizeof sp->s_login); 636 1.122 ad mutex_exit(&proc_lock); 637 1.75 enami return (0); 638 1.14 cgd } 639