1 /* $NetBSD: kern_prot.c,v 1.94 2006/09/08 20:58:57 elad Exp $ */ 2 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.9 (Berkeley) 2/14/95 37 */ 38 39 /* 40 * System calls related to processes and protection 41 */ 42 43 #include <sys/cdefs.h> 44 __KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.94 2006/09/08 20:58:57 elad Exp $"); 45 46 #include "opt_compat_43.h" 47 48 #include <sys/param.h> 49 #include <sys/acct.h> 50 #include <sys/systm.h> 51 #include <sys/ucred.h> 52 #include <sys/proc.h> 53 #include <sys/timeb.h> 54 #include <sys/times.h> 55 #include <sys/pool.h> 56 #include <sys/syslog.h> 57 #include <sys/resourcevar.h> 58 #include <sys/kauth.h> 59 60 #include <sys/mount.h> 61 #include <sys/sa.h> 62 #include <sys/syscallargs.h> 63 64 #include <sys/malloc.h> 65 66 int sys_getpid(struct lwp *, void *, register_t *); 67 int sys_getpid_with_ppid(struct lwp *, void *, register_t *); 68 int sys_getuid(struct lwp *, void *, register_t *); 69 int sys_getuid_with_euid(struct lwp *, void *, register_t *); 70 int sys_getgid(struct lwp *, void *, register_t *); 71 int sys_getgid_with_egid(struct lwp *, void *, register_t *); 72 73 static int grsortu(gid_t *, int); 74 75 /* ARGSUSED */ 76 int 77 sys_getpid(struct lwp *l, void *v, register_t *retval) 78 { 79 struct proc *p = l->l_proc; 80 81 *retval = p->p_pid; 82 return (0); 83 } 84 85 /* ARGSUSED */ 86 int 87 sys_getpid_with_ppid(struct lwp *l, void *v, register_t *retval) 88 { 89 struct proc *p = l->l_proc; 90 91 retval[0] = p->p_pid; 92 retval[1] = p->p_pptr->p_pid; 93 return (0); 94 } 95 96 /* ARGSUSED */ 97 int 98 sys_getppid(struct lwp *l, void *v, register_t *retval) 99 { 100 struct proc *p = l->l_proc; 101 102 *retval = p->p_pptr->p_pid; 103 return (0); 104 } 105 106 /* Get process group ID; note that POSIX getpgrp takes no parameter */ 107 int 108 sys_getpgrp(struct lwp *l, void *v, register_t *retval) 109 { 110 struct proc *p = l->l_proc; 111 112 *retval = p->p_pgrp->pg_id; 113 return (0); 114 } 115 116 /* 117 * Return the process group ID of the session leader (session ID) 118 * for the specified process. 119 */ 120 int 121 sys_getsid(struct lwp *l, void *v, register_t *retval) 122 { 123 struct sys_getsid_args /* { 124 syscalldarg(pid_t) pid; 125 } */ *uap = v; 126 struct proc *p = l->l_proc; 127 128 if (SCARG(uap, pid) == 0) 129 goto found; 130 if ((p = pfind(SCARG(uap, pid))) == 0) 131 return (ESRCH); 132 found: 133 *retval = p->p_session->s_sid; 134 return (0); 135 } 136 137 int 138 sys_getpgid(struct lwp *l, void *v, register_t *retval) 139 { 140 struct sys_getpgid_args /* { 141 syscallarg(pid_t) pid; 142 } */ *uap = v; 143 struct proc *p = l->l_proc; 144 145 if (SCARG(uap, pid) == 0) 146 goto found; 147 if ((p = pfind(SCARG(uap, pid))) == 0) 148 return (ESRCH); 149 found: 150 *retval = p->p_pgid; 151 return (0); 152 } 153 154 /* ARGSUSED */ 155 int 156 sys_getuid(struct lwp *l, void *v, register_t *retval) 157 { 158 159 *retval = kauth_cred_getuid(l->l_cred); 160 return (0); 161 } 162 163 /* ARGSUSED */ 164 int 165 sys_getuid_with_euid(struct lwp *l, void *v, register_t *retval) 166 { 167 168 retval[0] = kauth_cred_getuid(l->l_cred); 169 retval[1] = kauth_cred_geteuid(l->l_cred); 170 return (0); 171 } 172 173 /* ARGSUSED */ 174 int 175 sys_geteuid(struct lwp *l, void *v, register_t *retval) 176 { 177 178 *retval = kauth_cred_geteuid(l->l_cred); 179 return (0); 180 } 181 182 /* ARGSUSED */ 183 int 184 sys_getgid(struct lwp *l, void *v, register_t *retval) 185 { 186 187 *retval = kauth_cred_getgid(l->l_cred); 188 return (0); 189 } 190 191 /* ARGSUSED */ 192 int 193 sys_getgid_with_egid(struct lwp *l, void *v, register_t *retval) 194 { 195 196 retval[0] = kauth_cred_getgid(l->l_cred); 197 retval[1] = kauth_cred_getegid(l->l_cred); 198 return (0); 199 } 200 201 /* 202 * Get effective group ID. The "egid" is groups[0], and could be obtained 203 * via getgroups. This syscall exists because it is somewhat painful to do 204 * correctly in a library function. 205 */ 206 /* ARGSUSED */ 207 int 208 sys_getegid(struct lwp *l, void *v, register_t *retval) 209 { 210 211 *retval = kauth_cred_getegid(l->l_cred); 212 return (0); 213 } 214 215 int 216 sys_getgroups(struct lwp *l, void *v, register_t *retval) 217 { 218 struct sys_getgroups_args /* { 219 syscallarg(int) gidsetsize; 220 syscallarg(gid_t *) gidset; 221 } */ *uap = v; 222 kauth_cred_t cred = l->l_cred; 223 u_int ngrp; 224 int error; 225 gid_t *grbuf; 226 227 if (SCARG(uap, gidsetsize) == 0) { 228 *retval = kauth_cred_ngroups(cred); 229 return (0); 230 } else if (SCARG(uap, gidsetsize) < 0) 231 return (EINVAL); 232 ngrp = SCARG(uap, gidsetsize); 233 if (ngrp < kauth_cred_ngroups(cred)) 234 return (EINVAL); 235 ngrp = kauth_cred_ngroups(cred); 236 237 grbuf = malloc(ngrp * sizeof(*grbuf), M_TEMP, M_WAITOK); 238 kauth_cred_getgroups(cred, grbuf, ngrp); 239 error = copyout(grbuf, (caddr_t)SCARG(uap, gidset), 240 ngrp * sizeof(gid_t)); 241 free(grbuf, M_TEMP); 242 if (error) 243 return (error); 244 *retval = ngrp; 245 return (0); 246 } 247 248 /* ARGSUSED */ 249 int 250 sys_setsid(struct lwp *l, void *v, register_t *retval) 251 { 252 struct proc *p = l->l_proc; 253 254 if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 255 return (EPERM); 256 } else { 257 (void)enterpgrp(p, p->p_pid, 1); 258 *retval = p->p_pid; 259 return (0); 260 } 261 } 262 263 /* 264 * set process group (setpgid/old setpgrp) 265 * 266 * caller does setpgid(targpid, targpgid) 267 * 268 * pgid must be in valid range (EINVAL) 269 * pid must be caller or child of caller (ESRCH) 270 * if a child 271 * pid must be in same session (EPERM) 272 * pid can't have done an exec (EACCES) 273 * if pgid != pid 274 * there must exist some pid in same session having pgid (EPERM) 275 * pid must not be session leader (EPERM) 276 * 277 * Permission checks now in enterpgrp() 278 */ 279 /* ARGSUSED */ 280 int 281 sys_setpgid(struct lwp *l, void *v, register_t *retval) 282 { 283 struct sys_setpgid_args /* { 284 syscallarg(int) pid; 285 syscallarg(int) pgid; 286 } */ *uap = v; 287 struct proc *curp = l->l_proc; 288 struct proc *targp; /* target process */ 289 290 if (SCARG(uap, pgid) < 0) 291 return EINVAL; 292 293 /* XXX MP - there is a horrid race here with targp exiting! */ 294 if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != curp->p_pid) { 295 targp = pfind(SCARG(uap, pid)); 296 if (targp == NULL) 297 return ESRCH; 298 } else 299 targp = curp; 300 301 if (SCARG(uap, pgid) == 0) 302 SCARG(uap, pgid) = targp->p_pid; 303 return enterpgrp(targp, SCARG(uap, pgid), 0); 304 } 305 306 /* 307 * Set real, effective and saved uids to the requested values. 308 * non-root callers can only ever change uids to values that match 309 * one of the processes current uid values. 310 * This is further restricted by the flags argument. 311 */ 312 313 int 314 do_setresuid(struct lwp *l, uid_t r, uid_t e, uid_t sv, u_int flags) 315 { 316 struct proc *p = l->l_proc; 317 kauth_cred_t cred; 318 319 /* Get a write lock on the process credential. */ 320 proc_crmod_enter(p); 321 cred = p->p_cred; 322 323 /* 324 * Check that the new value is one of the allowed existing values, 325 * or that we have root privilege. 326 */ 327 if ((r != -1 328 && !((flags & ID_R_EQ_R) && r == kauth_cred_getuid(cred)) 329 && !((flags & ID_R_EQ_E) && r == kauth_cred_geteuid(cred)) 330 && !((flags & ID_R_EQ_S) && r == kauth_cred_getsvuid(cred))) || 331 (e != -1 332 && !((flags & ID_E_EQ_R) && e == kauth_cred_getuid(cred)) 333 && !((flags & ID_E_EQ_E) && e == kauth_cred_geteuid(cred)) 334 && !((flags & ID_E_EQ_S) && e == kauth_cred_getsvuid(cred))) || 335 (sv != -1 336 && !((flags & ID_S_EQ_R) && sv == kauth_cred_getuid(cred)) 337 && !((flags & ID_S_EQ_E) && sv == kauth_cred_geteuid(cred)) 338 && !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvuid(cred)))) { 339 int error; 340 341 error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID, 342 p, NULL, NULL, NULL); 343 if (error != 0) { 344 proc_crmod_leave(p, cred, NULL); 345 return error; 346 } 347 } 348 349 /* If nothing has changed, short circuit the request */ 350 if ((r == -1 || r == kauth_cred_getuid(cred)) 351 && (e == -1 || e == kauth_cred_geteuid(cred)) 352 && (sv == -1 || sv == kauth_cred_getsvuid(cred))) { 353 proc_crmod_leave(p, cred, NULL); 354 return 0; 355 } 356 357 cred = kauth_cred_dup(cred); 358 359 if (r != -1 && r != kauth_cred_getuid(cred)) { 360 /* Update count of processes for this user */ 361 (void)chgproccnt(kauth_cred_getuid(cred), -1); 362 (void)chgproccnt(r, 1); 363 kauth_cred_setuid(cred, r); 364 } 365 if (sv != -1) 366 kauth_cred_setsvuid(cred, sv); 367 if (e != -1) 368 kauth_cred_seteuid(cred, e); 369 370 /* Mark process as having changed credentials, stops tracing etc. */ 371 p_sugid(p); 372 373 /* Broadcast our credentials to the process and other LWPs. */ 374 proc_crmod_leave(p, cred, p->p_cred); 375 376 /* Update our copy of the credentials. */ 377 lwp_update_creds(l); 378 379 return 0; 380 } 381 382 /* 383 * Set real, effective and saved gids to the requested values. 384 * non-root callers can only ever change gids to values that match 385 * one of the processes current gid values. 386 * This is further restricted by the flags argument. 387 */ 388 389 int 390 do_setresgid(struct lwp *l, gid_t r, gid_t e, gid_t sv, u_int flags) 391 { 392 struct proc *p = l->l_proc; 393 kauth_cred_t cred; 394 395 /* Get a write lock on the process credential. */ 396 proc_crmod_enter(p); 397 cred = p->p_cred; 398 399 /* 400 * check new value is one of the allowed existing values. 401 * otherwise, check if we have root privilege. 402 */ 403 if ((r != -1 404 && !((flags & ID_R_EQ_R) && r == kauth_cred_getgid(cred)) 405 && !((flags & ID_R_EQ_E) && r == kauth_cred_getegid(cred)) 406 && !((flags & ID_R_EQ_S) && r == kauth_cred_getsvgid(cred))) || 407 (e != -1 408 && !((flags & ID_E_EQ_R) && e == kauth_cred_getgid(cred)) 409 && !((flags & ID_E_EQ_E) && e == kauth_cred_getegid(cred)) 410 && !((flags & ID_E_EQ_S) && e == kauth_cred_getsvgid(cred))) || 411 (sv != -1 412 && !((flags & ID_S_EQ_R) && sv == kauth_cred_getgid(cred)) 413 && !((flags & ID_S_EQ_E) && sv == kauth_cred_getegid(cred)) 414 && !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvgid(cred)))) { 415 int error; 416 417 error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID, 418 p, NULL, NULL, NULL); 419 if (error != 0) { 420 proc_crmod_leave(p, cred, NULL); 421 return error; 422 } 423 } 424 425 /* If nothing has changed, short circuit the request */ 426 if ((r == -1 || r == kauth_cred_getgid(cred)) 427 && (e == -1 || e == kauth_cred_getegid(cred)) 428 && (sv == -1 || sv == kauth_cred_getsvgid(cred))) { 429 proc_crmod_leave(p, cred, NULL); 430 return 0; 431 } 432 433 cred = kauth_cred_dup(cred); 434 435 if (r != -1) 436 kauth_cred_setgid(cred, r); 437 if (sv != -1) 438 kauth_cred_setsvgid(cred, sv); 439 if (e != -1) 440 kauth_cred_setegid(cred, e); 441 442 /* Mark process as having changed credentials, stops tracing etc. */ 443 p_sugid(p); 444 445 /* Broadcast our credentials to the process and other LWPs. */ 446 proc_crmod_leave(p, cred, p->p_cred); 447 448 /* Update our copy of the credentials. */ 449 lwp_update_creds(l); 450 451 return 0; 452 } 453 454 /* ARGSUSED */ 455 int 456 sys_setuid(struct lwp *l, void *v, register_t *retval) 457 { 458 struct sys_setuid_args /* { 459 syscallarg(uid_t) uid; 460 } */ *uap = v; 461 uid_t uid = SCARG(uap, uid); 462 463 return do_setresuid(l, uid, uid, uid, 464 ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R); 465 } 466 467 /* ARGSUSED */ 468 int 469 sys_seteuid(struct lwp *l, void *v, register_t *retval) 470 { 471 struct sys_seteuid_args /* { 472 syscallarg(uid_t) euid; 473 } */ *uap = v; 474 475 return do_setresuid(l, -1, SCARG(uap, euid), -1, ID_E_EQ_R | ID_E_EQ_S); 476 } 477 478 int 479 sys_setreuid(struct lwp *l, void *v, register_t *retval) 480 { 481 struct sys_setreuid_args /* { 482 syscallarg(uid_t) ruid; 483 syscallarg(uid_t) euid; 484 } */ *uap = v; 485 kauth_cred_t cred = l->l_cred; 486 uid_t ruid, euid, svuid; 487 488 ruid = SCARG(uap, ruid); 489 euid = SCARG(uap, euid); 490 491 if (ruid == -1) 492 ruid = kauth_cred_getuid(cred); 493 if (euid == -1) 494 euid = kauth_cred_geteuid(cred); 495 496 /* Saved uid is set to the new euid if the ruid changed */ 497 svuid = (ruid == kauth_cred_getuid(cred)) ? -1 : euid; 498 499 return do_setresuid(l, ruid, euid, svuid, 500 ID_R_EQ_R | ID_R_EQ_E | 501 ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S | 502 ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S); 503 } 504 505 /* ARGSUSED */ 506 int 507 sys_setgid(struct lwp *l, void *v, register_t *retval) 508 { 509 struct sys_setgid_args /* { 510 syscallarg(gid_t) gid; 511 } */ *uap = v; 512 gid_t gid = SCARG(uap, gid); 513 514 return do_setresgid(l, gid, gid, gid, 515 ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R); 516 } 517 518 /* ARGSUSED */ 519 int 520 sys_setegid(struct lwp *l, void *v, register_t *retval) 521 { 522 struct sys_setegid_args /* { 523 syscallarg(gid_t) egid; 524 } */ *uap = v; 525 526 return do_setresgid(l, -1, SCARG(uap, egid), -1, ID_E_EQ_R | ID_E_EQ_S); 527 } 528 529 int 530 sys_setregid(struct lwp *l, void *v, register_t *retval) 531 { 532 struct sys_setregid_args /* { 533 syscallarg(gid_t) rgid; 534 syscallarg(gid_t) egid; 535 } */ *uap = v; 536 kauth_cred_t cred = l->l_cred; 537 gid_t rgid, egid, svgid; 538 539 rgid = SCARG(uap, rgid); 540 egid = SCARG(uap, egid); 541 542 if (rgid == -1) 543 rgid = kauth_cred_getgid(cred); 544 if (egid == -1) 545 egid = kauth_cred_getegid(cred); 546 547 /* Saved gid is set to the new egid if the rgid changed */ 548 svgid = rgid == kauth_cred_getgid(cred) ? -1 : egid; 549 550 return do_setresgid(l, rgid, egid, svgid, 551 ID_R_EQ_R | ID_R_EQ_E | 552 ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S | 553 ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S); 554 } 555 556 int 557 sys_issetugid(struct lwp *l, void *v, register_t *retval) 558 { 559 struct proc *p = l->l_proc; 560 561 /* 562 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 563 * we use P_SUGID because we consider changing the owners as 564 * "tainting" as well. 565 * This is significant for procs that start as root and "become" 566 * a user without an exec - programs cannot know *everything* 567 * that libc *might* have put in their data segment. 568 */ 569 *retval = (p->p_flag & P_SUGID) != 0; 570 return (0); 571 } 572 573 /* 574 * sort -u for groups. 575 */ 576 static int 577 grsortu(gid_t *grp, int ngrp) 578 { 579 const gid_t *src, *end; 580 gid_t *dst; 581 gid_t group; 582 int i, j; 583 584 /* bubble sort */ 585 for (i = 0; i < ngrp; i++) 586 for (j = i + 1; j < ngrp; j++) 587 if (grp[i] > grp[j]) { 588 gid_t tmp = grp[i]; 589 grp[i] = grp[j]; 590 grp[j] = tmp; 591 } 592 593 /* uniq */ 594 end = grp + ngrp; 595 src = grp; 596 dst = grp; 597 while (src < end) { 598 group = *src++; 599 while (src < end && *src == group) 600 src++; 601 *dst++ = group; 602 } 603 604 #ifdef DIAGNOSTIC 605 /* zero out the rest of the array */ 606 (void)memset(dst, 0, sizeof(*grp) * (end - dst)); 607 #endif 608 609 return dst - grp; 610 } 611 612 /* ARGSUSED */ 613 int 614 sys_setgroups(struct lwp *l, void *v, register_t *retval) 615 { 616 struct sys_setgroups_args /* { 617 syscallarg(int) gidsetsize; 618 syscallarg(const gid_t *) gidset; 619 } */ *uap = v; 620 kauth_cred_t cred; 621 struct proc *p = l->l_proc; 622 int ngrp; 623 int error; 624 gid_t grp[NGROUPS]; 625 size_t grsize; 626 627 proc_crmod_enter(p); 628 cred = p->p_cred; 629 630 if ((error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID, 631 p, NULL, NULL, NULL)) != 0) 632 goto bad; 633 634 ngrp = SCARG(uap, gidsetsize); 635 if ((u_int)ngrp > NGROUPS) { 636 error = EINVAL; 637 goto bad; 638 } 639 640 grsize = ngrp * sizeof(gid_t); 641 error = copyin(SCARG(uap, gidset), grp, grsize); 642 if (error) 643 goto bad; 644 645 ngrp = grsortu(grp, ngrp); 646 cred = kauth_cred_dup(cred); 647 kauth_cred_setgroups(cred, grp, ngrp, -1); 648 649 /* Mark process as having changed credentials, stops tracing etc. */ 650 p_sugid(p); 651 652 /* Broadcast our credentials to the process and other LWPs. */ 653 proc_crmod_leave(p, cred, p->p_cred); 654 655 /* Update our copy of the credentials. */ 656 lwp_update_creds(l); 657 658 return (0); 659 bad: 660 proc_crmod_leave(p, cred, NULL); 661 return (error); 662 } 663 664 /* 665 * Get login name, if available. 666 */ 667 /* ARGSUSED */ 668 int 669 sys___getlogin(struct lwp *l, void *v, register_t *retval) 670 { 671 struct sys___getlogin_args /* { 672 syscallarg(char *) namebuf; 673 syscallarg(size_t) namelen; 674 } */ *uap = v; 675 struct proc *p = l->l_proc; 676 677 if (SCARG(uap, namelen) > sizeof(p->p_pgrp->pg_session->s_login)) 678 SCARG(uap, namelen) = sizeof(p->p_pgrp->pg_session->s_login); 679 return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, 680 (caddr_t) SCARG(uap, namebuf), SCARG(uap, namelen))); 681 } 682 683 /* 684 * Set login name. 685 */ 686 /* ARGSUSED */ 687 int 688 sys___setlogin(struct lwp *l, void *v, register_t *retval) 689 { 690 struct sys___setlogin_args /* { 691 syscallarg(const char *) namebuf; 692 } */ *uap = v; 693 struct proc *p = l->l_proc; 694 struct session *s = p->p_pgrp->pg_session; 695 char newname[sizeof s->s_login + 1]; 696 int error; 697 698 if ((error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_SETID, 699 p, NULL, NULL, NULL)) != 0) 700 return (error); 701 error = copyinstr(SCARG(uap, namebuf), &newname, sizeof newname, NULL); 702 if (error != 0) 703 return (error == ENAMETOOLONG ? EINVAL : error); 704 705 if (s->s_flags & S_LOGIN_SET && p->p_pid != s->s_sid && 706 strncmp(newname, s->s_login, sizeof s->s_login) != 0) 707 log(LOG_WARNING, "%s (pid %d) changing logname from " 708 "%.*s to %s\n", p->p_comm, p->p_pid, 709 (int)sizeof s->s_login, s->s_login, newname); 710 s->s_flags |= S_LOGIN_SET; 711 strncpy(s->s_login, newname, sizeof s->s_login); 712 return (0); 713 } 714