1 /* 2 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 39 * $FreeBSD$ 40 */ 41 42 /* 43 * System calls related to processes and protection 44 */ 45 46 #include "opt_compat.h" 47 #include "opt_global.h" 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/acct.h> 52 #include <sys/kernel.h> 53 #include <sys/lock.h> 54 #include <sys/mutex.h> 55 #include <sys/proc.h> 56 #include <sys/sysproto.h> 57 #include <sys/malloc.h> 58 #include <sys/pioctl.h> 59 #include <sys/resourcevar.h> 60 #include <sys/sysctl.h> 61 #include <sys/jail.h> 62 63 static MALLOC_DEFINE(M_CRED, "cred", "credentials"); 64 65 #ifndef _SYS_SYSPROTO_H_ 66 struct getpid_args { 67 int dummy; 68 }; 69 #endif 70 71 /* 72 * getpid - MP SAFE 73 */ 74 75 /* ARGSUSED */ 76 int 77 getpid(p, uap) 78 struct proc *p; 79 struct getpid_args *uap; 80 { 81 82 p->p_retval[0] = p->p_pid; 83 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 84 PROC_LOCK(p); 85 p->p_retval[1] = p->p_pptr->p_pid; 86 PROC_UNLOCK(p); 87 #endif 88 return (0); 89 } 90 91 /* 92 * getppid - MP SAFE 93 */ 94 95 #ifndef _SYS_SYSPROTO_H_ 96 struct getppid_args { 97 int dummy; 98 }; 99 #endif 100 /* ARGSUSED */ 101 int 102 getppid(p, uap) 103 struct proc *p; 104 struct getppid_args *uap; 105 { 106 107 PROC_LOCK(p); 108 p->p_retval[0] = p->p_pptr->p_pid; 109 PROC_UNLOCK(p); 110 return (0); 111 } 112 113 /* 114 * Get process group ID; note that POSIX getpgrp takes no parameter 115 * 116 * MP SAFE 117 */ 118 #ifndef _SYS_SYSPROTO_H_ 119 struct getpgrp_args { 120 int dummy; 121 }; 122 #endif 123 124 int 125 getpgrp(p, uap) 126 struct proc *p; 127 struct getpgrp_args *uap; 128 { 129 130 p->p_retval[0] = p->p_pgrp->pg_id; 131 return (0); 132 } 133 134 /* Get an arbitary pid's process group id */ 135 #ifndef _SYS_SYSPROTO_H_ 136 struct getpgid_args { 137 pid_t pid; 138 }; 139 #endif 140 141 int 142 getpgid(p, uap) 143 struct proc *p; 144 struct getpgid_args *uap; 145 { 146 struct proc *pt; 147 int error; 148 149 if (uap->pid == 0) 150 p->p_retval[0] = p->p_pgrp->pg_id; 151 else { 152 if ((pt = pfind(uap->pid)) == NULL) 153 return ESRCH; 154 if ((error = p_can(p, pt, P_CAN_SEE, NULL))) { 155 PROC_UNLOCK(pt); 156 return (error); 157 } 158 p->p_retval[0] = pt->p_pgrp->pg_id; 159 PROC_UNLOCK(pt); 160 } 161 return 0; 162 } 163 164 /* 165 * Get an arbitary pid's session id. 166 */ 167 #ifndef _SYS_SYSPROTO_H_ 168 struct getsid_args { 169 pid_t pid; 170 }; 171 #endif 172 173 int 174 getsid(p, uap) 175 struct proc *p; 176 struct getsid_args *uap; 177 { 178 struct proc *pt; 179 int error; 180 181 if (uap->pid == 0) 182 p->p_retval[0] = p->p_session->s_sid; 183 else { 184 if ((pt = pfind(uap->pid)) == NULL) 185 return ESRCH; 186 if ((error = p_can(p, pt, P_CAN_SEE, NULL))) { 187 PROC_UNLOCK(pt); 188 return (error); 189 } 190 p->p_retval[0] = pt->p_session->s_sid; 191 PROC_UNLOCK(pt); 192 } 193 return 0; 194 } 195 196 197 /* 198 * getuid() - MP SAFE 199 */ 200 #ifndef _SYS_SYSPROTO_H_ 201 struct getuid_args { 202 int dummy; 203 }; 204 #endif 205 206 /* ARGSUSED */ 207 int 208 getuid(p, uap) 209 struct proc *p; 210 struct getuid_args *uap; 211 { 212 213 p->p_retval[0] = p->p_ucred->cr_ruid; 214 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 215 p->p_retval[1] = p->p_ucred->cr_uid; 216 #endif 217 return (0); 218 } 219 220 /* 221 * geteuid() - MP SAFE 222 */ 223 #ifndef _SYS_SYSPROTO_H_ 224 struct geteuid_args { 225 int dummy; 226 }; 227 #endif 228 229 /* ARGSUSED */ 230 int 231 geteuid(p, uap) 232 struct proc *p; 233 struct geteuid_args *uap; 234 { 235 236 p->p_retval[0] = p->p_ucred->cr_uid; 237 return (0); 238 } 239 240 /* 241 * getgid() - MP SAFE 242 */ 243 #ifndef _SYS_SYSPROTO_H_ 244 struct getgid_args { 245 int dummy; 246 }; 247 #endif 248 249 /* ARGSUSED */ 250 int 251 getgid(p, uap) 252 struct proc *p; 253 struct getgid_args *uap; 254 { 255 256 p->p_retval[0] = p->p_ucred->cr_rgid; 257 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 258 p->p_retval[1] = p->p_ucred->cr_groups[0]; 259 #endif 260 return (0); 261 } 262 263 /* 264 * Get effective group ID. The "egid" is groups[0], and could be obtained 265 * via getgroups. This syscall exists because it is somewhat painful to do 266 * correctly in a library function. 267 */ 268 #ifndef _SYS_SYSPROTO_H_ 269 struct getegid_args { 270 int dummy; 271 }; 272 #endif 273 274 /* ARGSUSED */ 275 int 276 getegid(p, uap) 277 struct proc *p; 278 struct getegid_args *uap; 279 { 280 281 p->p_retval[0] = p->p_ucred->cr_groups[0]; 282 return (0); 283 } 284 285 #ifndef _SYS_SYSPROTO_H_ 286 struct getgroups_args { 287 u_int gidsetsize; 288 gid_t *gidset; 289 }; 290 #endif 291 int 292 getgroups(p, uap) 293 struct proc *p; 294 register struct getgroups_args *uap; 295 { 296 struct ucred *cred = p->p_ucred; 297 u_int ngrp; 298 int error; 299 300 if ((ngrp = uap->gidsetsize) == 0) { 301 p->p_retval[0] = cred->cr_ngroups; 302 return (0); 303 } 304 if (ngrp < cred->cr_ngroups) 305 return (EINVAL); 306 ngrp = cred->cr_ngroups; 307 if ((error = copyout((caddr_t)cred->cr_groups, 308 (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) 309 return (error); 310 p->p_retval[0] = ngrp; 311 return (0); 312 } 313 314 #ifndef _SYS_SYSPROTO_H_ 315 struct setsid_args { 316 int dummy; 317 }; 318 #endif 319 320 /* ARGSUSED */ 321 int 322 setsid(p, uap) 323 register struct proc *p; 324 struct setsid_args *uap; 325 { 326 327 if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 328 return (EPERM); 329 } else { 330 (void)enterpgrp(p, p->p_pid, 1); 331 p->p_retval[0] = p->p_pid; 332 return (0); 333 } 334 } 335 336 /* 337 * set process group (setpgid/old setpgrp) 338 * 339 * caller does setpgid(targpid, targpgid) 340 * 341 * pid must be caller or child of caller (ESRCH) 342 * if a child 343 * pid must be in same session (EPERM) 344 * pid can't have done an exec (EACCES) 345 * if pgid != pid 346 * there must exist some pid in same session having pgid (EPERM) 347 * pid must not be session leader (EPERM) 348 */ 349 #ifndef _SYS_SYSPROTO_H_ 350 struct setpgid_args { 351 int pid; /* target process id */ 352 int pgid; /* target pgrp id */ 353 }; 354 #endif 355 /* ARGSUSED */ 356 int 357 setpgid(curp, uap) 358 struct proc *curp; 359 register struct setpgid_args *uap; 360 { 361 register struct proc *targp; /* target process */ 362 register struct pgrp *pgrp; /* target pgrp */ 363 int error; 364 365 if (uap->pgid < 0) 366 return (EINVAL); 367 if (uap->pid != 0 && uap->pid != curp->p_pid) { 368 if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) { 369 if (targp) 370 PROC_UNLOCK(targp); 371 return (ESRCH); 372 } 373 if ((error = p_can(curproc, targp, P_CAN_SEE, NULL))) { 374 PROC_UNLOCK(targp); 375 return (error); 376 } 377 if (targp->p_pgrp == NULL || 378 targp->p_session != curp->p_session) { 379 PROC_UNLOCK(targp); 380 return (EPERM); 381 } 382 if (targp->p_flag & P_EXEC) { 383 PROC_UNLOCK(targp); 384 return (EACCES); 385 } 386 } else { 387 targp = curp; 388 PROC_LOCK(curp); /* XXX: not needed */ 389 } 390 if (SESS_LEADER(targp)) { 391 PROC_UNLOCK(targp); 392 return (EPERM); 393 } 394 if (uap->pgid == 0) 395 uap->pgid = targp->p_pid; 396 else if (uap->pgid != targp->p_pid) 397 if ((pgrp = pgfind(uap->pgid)) == 0 || 398 pgrp->pg_session != curp->p_session) { 399 PROC_UNLOCK(targp); 400 return (EPERM); 401 } 402 /* XXX: We should probably hold the lock across enterpgrp. */ 403 PROC_UNLOCK(targp); 404 return (enterpgrp(targp, uap->pgid, 0)); 405 } 406 407 /* 408 * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 409 * compatible. It says that setting the uid/gid to euid/egid is a special 410 * case of "appropriate privilege". Once the rules are expanded out, this 411 * basically means that setuid(nnn) sets all three id's, in all permitted 412 * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 413 * does not set the saved id - this is dangerous for traditional BSD 414 * programs. For this reason, we *really* do not want to set 415 * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 416 */ 417 #define POSIX_APPENDIX_B_4_2_2 418 419 #ifndef _SYS_SYSPROTO_H_ 420 struct setuid_args { 421 uid_t uid; 422 }; 423 #endif 424 /* ARGSUSED */ 425 int 426 setuid(p, uap) 427 struct proc *p; 428 struct setuid_args *uap; 429 { 430 struct ucred *newcred, *oldcred; 431 uid_t uid; 432 int error; 433 434 uid = uap->uid; 435 oldcred = p->p_ucred; 436 /* 437 * See if we have "permission" by POSIX 1003.1 rules. 438 * 439 * Note that setuid(geteuid()) is a special case of 440 * "appropriate privileges" in appendix B.4.2.2. We need 441 * to use this clause to be compatible with traditional BSD 442 * semantics. Basically, it means that "setuid(xx)" sets all 443 * three id's (assuming you have privs). 444 * 445 * Notes on the logic. We do things in three steps. 446 * 1: We determine if the euid is going to change, and do EPERM 447 * right away. We unconditionally change the euid later if this 448 * test is satisfied, simplifying that part of the logic. 449 * 2: We determine if the real and/or saved uid's are going to 450 * change. Determined by compile options. 451 * 3: Change euid last. (after tests in #2 for "appropriate privs") 452 */ 453 if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ 454 #ifdef _POSIX_SAVED_IDS 455 uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ 456 #endif 457 #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 458 uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ 459 #endif 460 (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) 461 return (error); 462 463 newcred = crdup(oldcred); 464 #ifdef _POSIX_SAVED_IDS 465 /* 466 * Do we have "appropriate privileges" (are we root or uid == euid) 467 * If so, we are changing the real uid and/or saved uid. 468 */ 469 if ( 470 #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 471 uid == oldcred->cr_uid || 472 #endif 473 suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */ 474 #endif 475 { 476 /* 477 * Set the real uid and transfer proc count to new user. 478 */ 479 if (uid != oldcred->cr_ruid) { 480 change_ruid(newcred, uid); 481 setsugid(p); 482 } 483 /* 484 * Set saved uid 485 * 486 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 487 * the security of seteuid() depends on it. B.4.2.2 says it 488 * is important that we should do this. 489 */ 490 if (uid != oldcred->cr_svuid) { 491 change_svuid(newcred, uid); 492 setsugid(p); 493 } 494 } 495 496 /* 497 * In all permitted cases, we are changing the euid. 498 * Copy credentials so other references do not see our changes. 499 */ 500 if (uid != oldcred->cr_uid) { 501 change_euid(newcred, uid); 502 setsugid(p); 503 } 504 p->p_ucred = newcred; 505 crfree(oldcred); 506 return (0); 507 } 508 509 #ifndef _SYS_SYSPROTO_H_ 510 struct seteuid_args { 511 uid_t euid; 512 }; 513 #endif 514 /* ARGSUSED */ 515 int 516 seteuid(p, uap) 517 struct proc *p; 518 struct seteuid_args *uap; 519 { 520 struct ucred *newcred, *oldcred; 521 uid_t euid; 522 int error; 523 524 euid = uap->euid; 525 oldcred = p->p_ucred; 526 if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ 527 euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ 528 (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) 529 return (error); 530 /* 531 * Everything's okay, do it. Copy credentials so other references do 532 * not see our changes. 533 */ 534 newcred = crdup(oldcred); 535 if (oldcred->cr_uid != euid) { 536 change_euid(newcred, euid); 537 setsugid(p); 538 } 539 p->p_ucred = newcred; 540 crfree(oldcred); 541 return (0); 542 } 543 544 #ifndef _SYS_SYSPROTO_H_ 545 struct setgid_args { 546 gid_t gid; 547 }; 548 #endif 549 /* ARGSUSED */ 550 int 551 setgid(p, uap) 552 struct proc *p; 553 struct setgid_args *uap; 554 { 555 struct ucred *newcred, *oldcred; 556 gid_t gid; 557 int error; 558 559 gid = uap->gid; 560 oldcred = p->p_ucred; 561 /* 562 * See if we have "permission" by POSIX 1003.1 rules. 563 * 564 * Note that setgid(getegid()) is a special case of 565 * "appropriate privileges" in appendix B.4.2.2. We need 566 * to use this clause to be compatible with traditional BSD 567 * semantics. Basically, it means that "setgid(xx)" sets all 568 * three id's (assuming you have privs). 569 * 570 * For notes on the logic here, see setuid() above. 571 */ 572 if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ 573 #ifdef _POSIX_SAVED_IDS 574 gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ 575 #endif 576 #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 577 gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ 578 #endif 579 (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) 580 return (error); 581 582 newcred = crdup(oldcred); 583 #ifdef _POSIX_SAVED_IDS 584 /* 585 * Do we have "appropriate privileges" (are we root or gid == egid) 586 * If so, we are changing the real uid and saved gid. 587 */ 588 if ( 589 #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 590 gid == oldcred->cr_groups[0] || 591 #endif 592 suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */ 593 #endif 594 { 595 /* 596 * Set real gid 597 */ 598 if (oldcred->cr_rgid != gid) { 599 change_rgid(newcred, gid); 600 setsugid(p); 601 } 602 /* 603 * Set saved gid 604 * 605 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 606 * the security of setegid() depends on it. B.4.2.2 says it 607 * is important that we should do this. 608 */ 609 if (oldcred->cr_svgid != gid) { 610 change_svgid(newcred, gid); 611 setsugid(p); 612 } 613 } 614 /* 615 * In all cases permitted cases, we are changing the egid. 616 * Copy credentials so other references do not see our changes. 617 */ 618 if (oldcred->cr_groups[0] != gid) { 619 change_egid(newcred, gid); 620 setsugid(p); 621 } 622 p->p_ucred = newcred; 623 crfree(oldcred); 624 return (0); 625 } 626 627 #ifndef _SYS_SYSPROTO_H_ 628 struct setegid_args { 629 gid_t egid; 630 }; 631 #endif 632 /* ARGSUSED */ 633 int 634 setegid(p, uap) 635 struct proc *p; 636 struct setegid_args *uap; 637 { 638 struct ucred *newcred, *oldcred; 639 gid_t egid; 640 int error; 641 642 egid = uap->egid; 643 oldcred = p->p_ucred; 644 if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ 645 egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ 646 (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) 647 return (error); 648 newcred = crdup(oldcred); 649 if (oldcred->cr_groups[0] != egid) { 650 change_egid(newcred, egid); 651 setsugid(p); 652 } 653 p->p_ucred = newcred; 654 crfree(oldcred); 655 return (0); 656 } 657 658 #ifndef _SYS_SYSPROTO_H_ 659 struct setgroups_args { 660 u_int gidsetsize; 661 gid_t *gidset; 662 }; 663 #endif 664 /* ARGSUSED */ 665 int 666 setgroups(p, uap) 667 struct proc *p; 668 struct setgroups_args *uap; 669 { 670 struct ucred *newcred, *oldcred; 671 u_int ngrp; 672 int error; 673 674 ngrp = uap->gidsetsize; 675 oldcred = p->p_ucred; 676 if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT))) 677 return (error); 678 if (ngrp > NGROUPS) 679 return (EINVAL); 680 /* 681 * XXX A little bit lazy here. We could test if anything has 682 * changed before crcopy() and setting P_SUGID. 683 */ 684 newcred = crdup(oldcred); 685 if (ngrp < 1) { 686 /* 687 * setgroups(0, NULL) is a legitimate way of clearing the 688 * groups vector on non-BSD systems (which generally do not 689 * have the egid in the groups[0]). We risk security holes 690 * when running non-BSD software if we do not do the same. 691 */ 692 newcred->cr_ngroups = 1; 693 } else { 694 if ((error = copyin((caddr_t)uap->gidset, 695 (caddr_t)newcred->cr_groups, ngrp * sizeof(gid_t)))) { 696 crfree(newcred); 697 return (error); 698 } 699 newcred->cr_ngroups = ngrp; 700 } 701 setsugid(p); 702 p->p_ucred = newcred; 703 crfree(oldcred); 704 return (0); 705 } 706 707 #ifndef _SYS_SYSPROTO_H_ 708 struct setreuid_args { 709 uid_t ruid; 710 uid_t euid; 711 }; 712 #endif 713 /* ARGSUSED */ 714 int 715 setreuid(p, uap) 716 register struct proc *p; 717 struct setreuid_args *uap; 718 { 719 struct ucred *newcred, *oldcred; 720 uid_t ruid, euid; 721 int error; 722 723 ruid = uap->ruid; 724 euid = uap->euid; 725 oldcred = p->p_ucred; 726 if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 727 ruid != oldcred->cr_svuid) || 728 (euid != (uid_t)-1 && euid != oldcred->cr_uid && 729 euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && 730 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) 731 return (error); 732 newcred = crdup(oldcred); 733 if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 734 change_euid(newcred, euid); 735 setsugid(p); 736 } 737 if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 738 change_ruid(newcred, ruid); 739 setsugid(p); 740 } 741 if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && 742 newcred->cr_svuid != newcred->cr_uid) { 743 change_svuid(newcred, newcred->cr_uid); 744 setsugid(p); 745 } 746 p->p_ucred = newcred; 747 crfree(oldcred); 748 return (0); 749 } 750 751 #ifndef _SYS_SYSPROTO_H_ 752 struct setregid_args { 753 gid_t rgid; 754 gid_t egid; 755 }; 756 #endif 757 /* ARGSUSED */ 758 int 759 setregid(p, uap) 760 register struct proc *p; 761 struct setregid_args *uap; 762 { 763 struct ucred *newcred, *oldcred; 764 gid_t rgid, egid; 765 int error; 766 767 rgid = uap->rgid; 768 egid = uap->egid; 769 oldcred = p->p_ucred; 770 if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 771 rgid != oldcred->cr_svgid) || 772 (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && 773 egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && 774 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) 775 return (error); 776 777 newcred = crdup(oldcred); 778 if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 779 change_egid(newcred, egid); 780 setsugid(p); 781 } 782 if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 783 change_rgid(newcred, rgid); 784 setsugid(p); 785 } 786 if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && 787 newcred->cr_svgid != newcred->cr_groups[0]) { 788 change_svgid(newcred, newcred->cr_groups[0]); 789 setsugid(p); 790 } 791 p->p_ucred = newcred; 792 crfree(oldcred); 793 return (0); 794 } 795 796 /* 797 * setresuid(ruid, euid, suid) is like setreuid except control over the 798 * saved uid is explicit. 799 */ 800 801 #ifndef _SYS_SYSPROTO_H_ 802 struct setresuid_args { 803 uid_t ruid; 804 uid_t euid; 805 uid_t suid; 806 }; 807 #endif 808 /* ARGSUSED */ 809 int 810 setresuid(p, uap) 811 register struct proc *p; 812 struct setresuid_args *uap; 813 { 814 struct ucred *newcred, *oldcred; 815 uid_t ruid, euid, suid; 816 int error; 817 818 ruid = uap->ruid; 819 euid = uap->euid; 820 suid = uap->suid; 821 oldcred = p->p_ucred; 822 if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && 823 ruid != oldcred->cr_svuid && 824 ruid != oldcred->cr_uid) || 825 (euid != (uid_t)-1 && euid != oldcred->cr_ruid && 826 euid != oldcred->cr_svuid && 827 euid != oldcred->cr_uid) || 828 (suid != (uid_t)-1 && suid != oldcred->cr_ruid && 829 suid != oldcred->cr_svuid && 830 suid != oldcred->cr_uid)) && 831 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) 832 return (error); 833 834 newcred = crdup(oldcred); 835 if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { 836 change_euid(newcred, euid); 837 setsugid(p); 838 } 839 if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { 840 change_ruid(newcred, ruid); 841 setsugid(p); 842 } 843 if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { 844 change_svuid(newcred, suid); 845 setsugid(p); 846 } 847 p->p_ucred = newcred; 848 crfree(oldcred); 849 return (0); 850 } 851 852 /* 853 * setresgid(rgid, egid, sgid) is like setregid except control over the 854 * saved gid is explicit. 855 */ 856 857 #ifndef _SYS_SYSPROTO_H_ 858 struct setresgid_args { 859 gid_t rgid; 860 gid_t egid; 861 gid_t sgid; 862 }; 863 #endif 864 /* ARGSUSED */ 865 int 866 setresgid(p, uap) 867 register struct proc *p; 868 struct setresgid_args *uap; 869 { 870 struct ucred *newcred, *oldcred; 871 gid_t rgid, egid, sgid; 872 int error; 873 874 rgid = uap->rgid; 875 egid = uap->egid; 876 sgid = uap->sgid; 877 oldcred = p->p_ucred; 878 if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && 879 rgid != oldcred->cr_svgid && 880 rgid != oldcred->cr_groups[0]) || 881 (egid != (gid_t)-1 && egid != oldcred->cr_rgid && 882 egid != oldcred->cr_svgid && 883 egid != oldcred->cr_groups[0]) || 884 (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && 885 sgid != oldcred->cr_svgid && 886 sgid != oldcred->cr_groups[0])) && 887 (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) 888 return (error); 889 890 newcred = crdup(oldcred); 891 if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { 892 change_egid(newcred, egid); 893 setsugid(p); 894 } 895 if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { 896 change_rgid(newcred, rgid); 897 setsugid(p); 898 } 899 if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) { 900 change_svgid(newcred, sgid); 901 setsugid(p); 902 } 903 p->p_ucred = newcred; 904 crfree(oldcred); 905 return (0); 906 } 907 908 #ifndef _SYS_SYSPROTO_H_ 909 struct getresuid_args { 910 uid_t *ruid; 911 uid_t *euid; 912 uid_t *suid; 913 }; 914 #endif 915 /* ARGSUSED */ 916 int 917 getresuid(p, uap) 918 register struct proc *p; 919 struct getresuid_args *uap; 920 { 921 struct ucred *cred = p->p_ucred; 922 int error1 = 0, error2 = 0, error3 = 0; 923 924 if (uap->ruid) 925 error1 = copyout((caddr_t)&cred->cr_ruid, 926 (caddr_t)uap->ruid, sizeof(cred->cr_ruid)); 927 if (uap->euid) 928 error2 = copyout((caddr_t)&cred->cr_uid, 929 (caddr_t)uap->euid, sizeof(cred->cr_uid)); 930 if (uap->suid) 931 error3 = copyout((caddr_t)&cred->cr_svuid, 932 (caddr_t)uap->suid, sizeof(cred->cr_svuid)); 933 return error1 ? error1 : (error2 ? error2 : error3); 934 } 935 936 #ifndef _SYS_SYSPROTO_H_ 937 struct getresgid_args { 938 gid_t *rgid; 939 gid_t *egid; 940 gid_t *sgid; 941 }; 942 #endif 943 /* ARGSUSED */ 944 int 945 getresgid(p, uap) 946 register struct proc *p; 947 struct getresgid_args *uap; 948 { 949 struct ucred *cred = p->p_ucred; 950 int error1 = 0, error2 = 0, error3 = 0; 951 952 if (uap->rgid) 953 error1 = copyout((caddr_t)&cred->cr_rgid, 954 (caddr_t)uap->rgid, sizeof(cred->cr_rgid)); 955 if (uap->egid) 956 error2 = copyout((caddr_t)&cred->cr_groups[0], 957 (caddr_t)uap->egid, sizeof(cred->cr_groups[0])); 958 if (uap->sgid) 959 error3 = copyout((caddr_t)&cred->cr_svgid, 960 (caddr_t)uap->sgid, sizeof(cred->cr_svgid)); 961 return error1 ? error1 : (error2 ? error2 : error3); 962 } 963 964 965 #ifndef _SYS_SYSPROTO_H_ 966 struct issetugid_args { 967 int dummy; 968 }; 969 #endif 970 /* ARGSUSED */ 971 int 972 issetugid(p, uap) 973 register struct proc *p; 974 struct issetugid_args *uap; 975 { 976 /* 977 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 978 * we use P_SUGID because we consider changing the owners as 979 * "tainting" as well. 980 * This is significant for procs that start as root and "become" 981 * a user without an exec - programs cannot know *everything* 982 * that libc *might* have put in their data segment. 983 */ 984 p->p_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 985 return (0); 986 } 987 988 int 989 __setugid(p, uap) 990 struct proc *p; 991 struct __setugid_args *uap; 992 { 993 994 #ifdef REGRESSION 995 switch (uap->flag) { 996 case 0: 997 p->p_flag &= ~P_SUGID; 998 return (0); 999 case 1: 1000 p->p_flag |= P_SUGID; 1001 return (0); 1002 default: 1003 return (EINVAL); 1004 } 1005 #else /* !REGRESSION */ 1006 return (ENOSYS); 1007 #endif /* !REGRESSION */ 1008 } 1009 1010 /* 1011 * Check if gid is a member of the group set. 1012 */ 1013 int 1014 groupmember(gid, cred) 1015 gid_t gid; 1016 struct ucred *cred; 1017 { 1018 register gid_t *gp; 1019 gid_t *egp; 1020 1021 egp = &(cred->cr_groups[cred->cr_ngroups]); 1022 for (gp = cred->cr_groups; gp < egp; gp++) 1023 if (*gp == gid) 1024 return (1); 1025 return (0); 1026 } 1027 1028 static int suser_permitted = 1; 1029 1030 SYSCTL_INT(_kern, OID_AUTO, suser_permitted, CTLFLAG_RW, &suser_permitted, 0, 1031 "processes with uid 0 have privilege"); 1032 1033 /* 1034 * Test whether the specified credentials imply "super-user" 1035 * privilege; if so, and we have accounting info, set the flag 1036 * indicating use of super-powers. 1037 * Returns 0 or error. 1038 */ 1039 int 1040 suser(p) 1041 struct proc *p; 1042 { 1043 return suser_xxx(0, p, 0); 1044 } 1045 1046 int 1047 suser_xxx(cred, proc, flag) 1048 struct ucred *cred; 1049 struct proc *proc; 1050 int flag; 1051 { 1052 if (!suser_permitted) 1053 return (EPERM); 1054 if (!cred && !proc) { 1055 printf("suser_xxx(): THINK!\n"); 1056 return (EPERM); 1057 } 1058 if (!cred) 1059 cred = proc->p_ucred; 1060 if (cred->cr_uid != 0) 1061 return (EPERM); 1062 if (jailed(cred) && !(flag & PRISON_ROOT)) 1063 return (EPERM); 1064 return (0); 1065 } 1066 1067 /* 1068 * u_cansee(u1, u2): determine if u1 "can see" the subject specified by u2 1069 * Arguments: imutable credentials u1, u2 1070 * Returns: 0 for permitted, an errno value otherwise 1071 * Locks: none 1072 * References: u1 and u2 must be valid for the lifetime of the call 1073 * u1 may equal u2, in which case only one reference is required 1074 */ 1075 int 1076 u_cansee(struct ucred *u1, struct ucred *u2) 1077 { 1078 int error; 1079 1080 if ((error = prison_check(u1, u2))) 1081 return (error); 1082 if (!ps_showallprocs && u1->cr_ruid != u2->cr_ruid) { 1083 if (suser_xxx(u1, NULL, PRISON_ROOT) != 0) 1084 return (ESRCH); 1085 } 1086 return (0); 1087 } 1088 1089 static int 1090 p_cansee(struct proc *p1, struct proc *p2, int *privused) 1091 { 1092 1093 /* XXX: privused is going away, so don't do that here. */ 1094 if (privused != NULL) 1095 *privused = 0; 1096 /* Wrap u_cansee() for all functionality. */ 1097 return (u_cansee(p1->p_ucred, p2->p_ucred)); 1098 } 1099 1100 /* 1101 * Can process p1 send the signal signum to process p2? 1102 */ 1103 int 1104 p_cansignal(struct proc *p1, struct proc *p2, int signum) 1105 { 1106 int error; 1107 1108 if (p1 == p2) 1109 return (0); 1110 1111 /* 1112 * Jail semantics limit the scope of signalling to p2 in the same 1113 * jail as p1, if p1 is in jail. 1114 */ 1115 if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 1116 return (error); 1117 1118 /* 1119 * UNIX signalling semantics require that processes in the same 1120 * session always be able to deliver SIGCONT to one another, 1121 * overriding the remaining protections. 1122 */ 1123 if (signum == SIGCONT && p1->p_session == p2->p_session) 1124 return (0); 1125 1126 /* 1127 * UNIX uid semantics depend on the status of the P_SUGID 1128 * bit on the target process. If the bit is set, then more 1129 * restricted signal sets are permitted. 1130 */ 1131 if (p2->p_flag & P_SUGID) { 1132 switch (signum) { 1133 case 0: 1134 case SIGKILL: 1135 case SIGINT: 1136 case SIGTERM: 1137 case SIGSTOP: 1138 case SIGTTIN: 1139 case SIGTTOU: 1140 case SIGTSTP: 1141 case SIGHUP: 1142 case SIGUSR1: 1143 case SIGUSR2: 1144 break; 1145 default: 1146 /* Not permitted, try privilege. */ 1147 error = suser_xxx(NULL, p1, PRISON_ROOT); 1148 if (error) 1149 return (error); 1150 } 1151 } 1152 1153 /* 1154 * Generally, the object credential's ruid or svuid must match the 1155 * subject credential's ruid or euid. 1156 */ 1157 if (p1->p_ucred->cr_ruid != p2->p_ucred->cr_ruid && 1158 p1->p_ucred->cr_ruid != p2->p_ucred->cr_svuid && 1159 p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid && 1160 p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid) { 1161 /* Not permitted, try privilege. */ 1162 error = suser_xxx(NULL, p1, PRISON_ROOT); 1163 if (error) 1164 return (error); 1165 } 1166 1167 return (0); 1168 } 1169 1170 static int 1171 p_cansched(struct proc *p1, struct proc *p2, int *privused) 1172 { 1173 int error; 1174 1175 if (privused != NULL) 1176 *privused = 0; 1177 1178 if (p1 == p2) 1179 return (0); 1180 1181 if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 1182 return (error); 1183 1184 if (p1->p_ucred->cr_ruid == p2->p_ucred->cr_ruid) 1185 return (0); 1186 if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid) 1187 return (0); 1188 1189 if (!suser_xxx(0, p1, PRISON_ROOT)) { 1190 if (privused != NULL) 1191 *privused = 1; 1192 return (0); 1193 } 1194 1195 #ifdef CAPABILITIES 1196 if (!cap_check_xxx(0, p1, CAP_SYS_NICE, PRISON_ROOT)) { 1197 if (privused != NULL) 1198 *privused = 1; 1199 return (0); 1200 } 1201 #endif 1202 1203 return (EPERM); 1204 } 1205 1206 static int 1207 p_candebug(struct proc *p1, struct proc *p2, int *privused) 1208 { 1209 int error; 1210 1211 if (privused != NULL) 1212 *privused = 0; 1213 1214 if (p1 == p2) 1215 return (0); 1216 1217 if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 1218 return (error); 1219 1220 /* not owned by you, has done setuid (unless you're root) */ 1221 /* add a CAP_SYS_PTRACE here? */ 1222 if (p1->p_ucred->cr_uid != p2->p_ucred->cr_uid || 1223 p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid || 1224 p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid || 1225 p2->p_flag & P_SUGID) { 1226 if ((error = suser_xxx(0, p1, PRISON_ROOT))) 1227 return (error); 1228 if (privused != NULL) 1229 *privused = 1; 1230 } 1231 1232 /* can't trace init when securelevel > 0 */ 1233 if (securelevel > 0 && p2->p_pid == 1) 1234 return (EPERM); 1235 1236 return (0); 1237 } 1238 1239 int 1240 p_can(struct proc *p1, struct proc *p2, int operation, 1241 int *privused) 1242 { 1243 1244 switch(operation) { 1245 case P_CAN_SEE: 1246 return (p_cansee(p1, p2, privused)); 1247 1248 case P_CAN_SCHED: 1249 return (p_cansched(p1, p2, privused)); 1250 1251 case P_CAN_DEBUG: 1252 return (p_candebug(p1, p2, privused)); 1253 1254 default: 1255 panic("p_can: invalid operation"); 1256 } 1257 } 1258 1259 1260 /* 1261 * Allocate a zeroed cred structure. 1262 */ 1263 struct ucred * 1264 crget() 1265 { 1266 register struct ucred *cr; 1267 1268 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK|M_ZERO); 1269 cr->cr_ref = 1; 1270 mtx_init(&cr->cr_mtx, "ucred", MTX_DEF); 1271 return (cr); 1272 } 1273 1274 /* 1275 * Claim another reference to a ucred structure 1276 */ 1277 void 1278 crhold(cr) 1279 struct ucred *cr; 1280 { 1281 1282 mtx_lock(&cr->cr_mtx); 1283 cr->cr_ref++; 1284 mtx_unlock(&(cr)->cr_mtx); 1285 } 1286 1287 1288 /* 1289 * Free a cred structure. 1290 * Throws away space when ref count gets to 0. 1291 */ 1292 void 1293 crfree(cr) 1294 struct ucred *cr; 1295 { 1296 1297 mtx_lock(&cr->cr_mtx); 1298 KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1299 if (--cr->cr_ref == 0) { 1300 mtx_destroy(&cr->cr_mtx); 1301 /* 1302 * Some callers of crget(), such as nfs_statfs(), 1303 * allocate a temporary credential, but don't 1304 * allocate a uidinfo structure. 1305 */ 1306 if (cr->cr_uidinfo != NULL) 1307 uifree(cr->cr_uidinfo); 1308 if (cr->cr_ruidinfo != NULL) 1309 uifree(cr->cr_ruidinfo); 1310 /* 1311 * Free a prison, if any. 1312 */ 1313 if (jailed(cr)) 1314 prison_free(cr->cr_prison); 1315 FREE((caddr_t)cr, M_CRED); 1316 } else { 1317 mtx_unlock(&cr->cr_mtx); 1318 } 1319 } 1320 1321 /* 1322 * Copy cred structure to a new one and free the old one. 1323 */ 1324 struct ucred * 1325 crcopy(cr) 1326 struct ucred *cr; 1327 { 1328 struct ucred *newcr; 1329 1330 mtx_lock(&cr->cr_mtx); 1331 if (cr->cr_ref == 1) { 1332 mtx_unlock(&cr->cr_mtx); 1333 return (cr); 1334 } 1335 mtx_unlock(&cr->cr_mtx); 1336 newcr = crdup(cr); 1337 crfree(cr); 1338 return (newcr); 1339 } 1340 1341 /* 1342 * Dup cred struct to a new held one. 1343 */ 1344 struct ucred * 1345 crdup(cr) 1346 struct ucred *cr; 1347 { 1348 struct ucred *newcr; 1349 1350 MALLOC(newcr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 1351 *newcr = *cr; 1352 mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF); 1353 uihold(newcr->cr_uidinfo); 1354 uihold(newcr->cr_ruidinfo); 1355 if (jailed(newcr)) 1356 prison_hold(newcr->cr_prison); 1357 newcr->cr_ref = 1; 1358 return (newcr); 1359 } 1360 1361 /* 1362 * Get login name, if available. 1363 */ 1364 #ifndef _SYS_SYSPROTO_H_ 1365 struct getlogin_args { 1366 char *namebuf; 1367 u_int namelen; 1368 }; 1369 #endif 1370 /* ARGSUSED */ 1371 int 1372 getlogin(p, uap) 1373 struct proc *p; 1374 struct getlogin_args *uap; 1375 { 1376 1377 if (uap->namelen > MAXLOGNAME) 1378 uap->namelen = MAXLOGNAME; 1379 return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, 1380 (caddr_t) uap->namebuf, uap->namelen)); 1381 } 1382 1383 /* 1384 * Set login name. 1385 */ 1386 #ifndef _SYS_SYSPROTO_H_ 1387 struct setlogin_args { 1388 char *namebuf; 1389 }; 1390 #endif 1391 /* ARGSUSED */ 1392 int 1393 setlogin(p, uap) 1394 struct proc *p; 1395 struct setlogin_args *uap; 1396 { 1397 int error; 1398 char logintmp[MAXLOGNAME]; 1399 1400 if ((error = suser_xxx(0, p, PRISON_ROOT))) 1401 return (error); 1402 error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 1403 sizeof(logintmp), (size_t *)0); 1404 if (error == ENAMETOOLONG) 1405 error = EINVAL; 1406 else if (!error) 1407 (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp, 1408 sizeof(logintmp)); 1409 return (error); 1410 } 1411 1412 void 1413 setsugid(p) 1414 struct proc *p; 1415 { 1416 p->p_flag |= P_SUGID; 1417 if (!(p->p_pfsflags & PF_ISUGID)) 1418 p->p_stops = 0; 1419 } 1420 1421 /* 1422 * change_euid(): Change a process's effective uid. 1423 * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. 1424 * References: newcred must be an exclusive credential reference for the 1425 * duration of the call. 1426 */ 1427 void 1428 change_euid(newcred, euid) 1429 struct ucred *newcred; 1430 uid_t euid; 1431 { 1432 1433 newcred->cr_uid = euid; 1434 uifree(newcred->cr_uidinfo); 1435 newcred->cr_uidinfo = uifind(euid); 1436 } 1437 1438 /* 1439 * change_egid(): Change a process's effective gid. 1440 * Side effects: newcred->cr_gid will be modified. 1441 * References: newcred must be an exclusive credential reference for the 1442 * duration of the call. 1443 */ 1444 void 1445 change_egid(newcred, egid) 1446 struct ucred *newcred; 1447 gid_t egid; 1448 { 1449 1450 newcred->cr_groups[0] = egid; 1451 } 1452 1453 /* 1454 * change_ruid(): Change a process's real uid. 1455 * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo 1456 * will be updated, and the old and new cr_ruidinfo proc 1457 * counts will be updated. 1458 * References: newcred must be an exclusive credential reference for the 1459 * duration of the call. 1460 */ 1461 void 1462 change_ruid(newcred, ruid) 1463 struct ucred *newcred; 1464 uid_t ruid; 1465 { 1466 1467 (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); 1468 newcred->cr_ruid = ruid; 1469 uifree(newcred->cr_ruidinfo); 1470 newcred->cr_ruidinfo = uifind(ruid); 1471 (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); 1472 } 1473 1474 /* 1475 * change_rgid(): Change a process's real gid. 1476 * Side effects: newcred->cr_rgid will be updated. 1477 * References: newcred must be an exclusive credential reference for the 1478 * duration of the call. 1479 */ 1480 void 1481 change_rgid(newcred, rgid) 1482 struct ucred *newcred; 1483 gid_t rgid; 1484 { 1485 1486 newcred->cr_rgid = rgid; 1487 } 1488 1489 /* 1490 * change_svuid(): Change a process's saved uid. 1491 * Side effects: newcred->cr_svuid will be updated. 1492 * References: newcred must be an exclusive credential reference for the 1493 * duration of the call. 1494 */ 1495 void 1496 change_svuid(newcred, svuid) 1497 struct ucred *newcred; 1498 uid_t svuid; 1499 { 1500 1501 newcred->cr_svuid = svuid; 1502 } 1503 1504 /* 1505 * change_svgid(): Change a process's saved gid. 1506 * Side effects: newcred->cr_svgid will be updated. 1507 * References: newcred must be an exclusive credential reference for the 1508 * duration of the call. 1509 */ 1510 void 1511 change_svgid(newcred, svgid) 1512 struct ucred *newcred; 1513 gid_t svgid; 1514 { 1515 1516 newcred->cr_svgid = svgid; 1517 } 1518