Module Name: src Committed By: dholland Date: Sun Mar 13 00:32:09 UTC 2016
Modified Files: src/libexec/atrun: Makefile atrun.c src/usr.bin/at: Makefile at.c panic.c perm.c privs.h Added Files: src/usr.bin/at: privs.c Log Message: Use functions instead of preprocessor abuse. To generate a diff of this commit: cvs rdiff -u -r1.14 -r1.15 src/libexec/atrun/Makefile cvs rdiff -u -r1.21 -r1.22 src/libexec/atrun/atrun.c cvs rdiff -u -r1.11 -r1.12 src/usr.bin/at/Makefile cvs rdiff -u -r1.30 -r1.31 src/usr.bin/at/at.c cvs rdiff -u -r1.13 -r1.14 src/usr.bin/at/panic.c cvs rdiff -u -r1.3 -r1.4 src/usr.bin/at/perm.c cvs rdiff -u -r0 -r1.1 src/usr.bin/at/privs.c cvs rdiff -u -r1.8 -r1.9 src/usr.bin/at/privs.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/libexec/atrun/Makefile diff -u src/libexec/atrun/Makefile:1.14 src/libexec/atrun/Makefile:1.15 --- src/libexec/atrun/Makefile:1.14 Tue Aug 16 10:35:03 2011 +++ src/libexec/atrun/Makefile Sun Mar 13 00:32:09 2016 @@ -1,11 +1,15 @@ -# $NetBSD: Makefile,v 1.14 2011/08/16 10:35:03 christos Exp $ +# $NetBSD: Makefile,v 1.15 2016/03/13 00:32:09 dholland Exp $ .include <bsd.own.mk> PROG= atrun +SRCS= atrun.c BINDIR= /usr/libexec MAN= atrun.8 +.PATH.c: ${NETBSDSRCDIR}/usr.bin/at +SRCS+= privs.c + CPPFLAGS+= -I${NETBSDSRCDIR}/usr.bin/at COPTS.atrun.c = -Wno-format-nonliteral Index: src/libexec/atrun/atrun.c diff -u src/libexec/atrun/atrun.c:1.21 src/libexec/atrun/atrun.c:1.22 --- src/libexec/atrun/atrun.c:1.21 Fri Sep 16 16:13:17 2011 +++ src/libexec/atrun/atrun.c Sun Mar 13 00:32:09 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: atrun.c,v 1.21 2011/09/16 16:13:17 plunky Exp $ */ +/* $NetBSD: atrun.c,v 1.22 2016/03/13 00:32:09 dholland Exp $ */ /* * atrun.c - run jobs queued by at; run with root privileges. @@ -49,7 +49,6 @@ /* Local headers */ -#define MAIN #include "privs.h" #include "pathnames.h" #include "atrun.h" @@ -59,7 +58,7 @@ #if 0 static char rcsid[] = "$OpenBSD: atrun.c,v 1.7 1997/09/08 22:12:10 millert Exp $"; #else -__RCSID("$NetBSD: atrun.c,v 1.21 2011/09/16 16:13:17 plunky Exp $"); +__RCSID("$NetBSD: atrun.c,v 1.22 2016/03/13 00:32:09 dholland Exp $"); #endif static int debug = 0; @@ -108,6 +107,12 @@ perrx(const char *fmt, ...) exit(EXIT_FAILURE); } +__dead void +privs_fail(const char *msg) +{ + perr("%s", msg); +} + static int write_string(int fd, const char *a) { @@ -160,12 +165,12 @@ run_file(const char *filename, uid_t uid gid_t ngid; int serrno; - PRIV_START; + privs_enter(); if (chmod(filename, S_IRUSR) == -1) perr("Cannot change file permissions to `%s'", filename); - PRIV_END; + privs_exit(); pid = fork(); if (pid == -1) @@ -184,12 +189,12 @@ run_file(const char *filename, uid_t uid perrx("Userid %lu not found - aborting job `%s'", (unsigned long)uid, filename); - PRIV_START; + privs_enter(); stream = fopen(filename, "r"); serrno = errno; - PRIV_END; + privs_exit(); if (stream == NULL) { errno = serrno; @@ -206,12 +211,12 @@ run_file(const char *filename, uid_t uid if (fstat(fd_in, &buf) == -1) perr("Error in fstat of input file descriptor"); - PRIV_START; + privs_enter(); if (lstat(filename, &lbuf) == -1) perr("Error in lstat of `%s'", filename); - PRIV_END; + privs_exit(); if (S_ISLNK(lbuf.st_mode)) perrx("Symbolic link encountered in job `%s' - aborting", @@ -253,7 +258,7 @@ run_file(const char *filename, uid_t uid (void)fclose(stream); - PRIV_START; + privs_enter(); if (chdir(_PATH_ATSPOOL) == -1) perr("Cannot chdir to `%s'", _PATH_ATSPOOL); @@ -267,7 +272,7 @@ run_file(const char *filename, uid_t uid O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) == -1) perr("Cannot create output file `%s'", filename); - PRIV_END; + privs_exit(); write_string(fd_out, "To: "); write_string(fd_out, mailname); @@ -309,7 +314,7 @@ run_file(const char *filename, uid_t uid (void)close(fd_in); (void)close(fd_out); - PRIV_START; + privs_enter(); if (chdir(_PATH_ATJOBS) == -1) perr("Cannot chdir to `%s'", _PATH_ATJOBS); @@ -333,7 +338,7 @@ run_file(const char *filename, uid_t uid * Send mail. Unlink the output file first, so it is deleted * after the run. */ - PRIV_START; + privs_enter(); if (stat(filename, &buf) == -1) perr("Error in stat of output file `%s'", filename); @@ -342,12 +347,12 @@ run_file(const char *filename, uid_t uid (void)unlink(filename); - PRIV_END; + privs_exit(); if ((buf.st_size != size) || send_mail) { /* Fork off a child for sending mail */ - PRIV_START; + privs_enter(); become_user(pentry, uid); @@ -355,7 +360,7 @@ run_file(const char *filename, uid_t uid "-odi", "-oem", "-t", (char *) NULL); perr("Exec failed for mail command `%s'", _PATH_SENDMAIL); - PRIV_END; + privs_exit(); } exit(EXIT_SUCCESS); } @@ -406,7 +411,7 @@ main(int argc, char *argv[]) * We don't need root privileges all the time; running under uid * and gid nobody is fine except for privileged operations. */ - RELINQUISH_PRIVS_ROOT(pwd->pw_uid, grp->gr_gid); + privs_relinquish_root(pwd->pw_uid, grp->gr_gid); opterr = 0; errno = 0; @@ -433,7 +438,7 @@ main(int argc, char *argv[]) } } - PRIV_START; + privs_enter(); if (chdir(_PATH_ATJOBS) == -1) perr("Cannot change directory to `%s'", _PATH_ATJOBS); @@ -453,7 +458,7 @@ main(int argc, char *argv[]) if ((spool = opendir(".")) == NULL) perr("Cannot open `%s'", _PATH_ATJOBS); - PRIV_END; + privs_exit(); now = time(NULL); run_batch = 0; @@ -461,13 +466,13 @@ main(int argc, char *argv[]) batch_gid = (gid_t) -1; while ((dirent = readdir(spool)) != NULL) { - PRIV_START; + privs_enter(); if (stat(dirent->d_name, &buf) == -1) perr("Cannot stat `%s' in `%s'", dirent->d_name, _PATH_ATJOBS); - PRIV_END; + privs_exit(); /* We don't want directories */ if (!S_ISREG(buf.st_mode)) @@ -498,11 +503,11 @@ main(int argc, char *argv[]) /* Delete older files */ if ((run_time < now) && !(S_IXUSR & buf.st_mode) && (S_IRUSR & buf.st_mode)) { - PRIV_START; + privs_enter(); (void)unlink(dirent->d_name); - PRIV_END; + privs_exit(); } } Index: src/usr.bin/at/Makefile diff -u src/usr.bin/at/Makefile:1.11 src/usr.bin/at/Makefile:1.12 --- src/usr.bin/at/Makefile:1.11 Tue Apr 14 22:15:17 2009 +++ src/usr.bin/at/Makefile Sun Mar 13 00:32:09 2016 @@ -1,9 +1,9 @@ -# $NetBSD: Makefile,v 1.11 2009/04/14 22:15:17 lukem Exp $ +# $NetBSD: Makefile,v 1.12 2016/03/13 00:32:09 dholland Exp $ USE_FORT?= yes # setuid PROG= at -SRCS= at.c panic.c parsetime.c perm.c stime.c +SRCS= at.c panic.c parsetime.c perm.c privs.c stime.c LINKS= ${BINDIR}/at ${BINDIR}/atq \ ${BINDIR}/at ${BINDIR}/atrm \ ${BINDIR}/at ${BINDIR}/batch Index: src/usr.bin/at/at.c diff -u src/usr.bin/at/at.c:1.30 src/usr.bin/at/at.c:1.31 --- src/usr.bin/at/at.c:1.30 Mon Aug 29 14:24:03 2011 +++ src/usr.bin/at/at.c Sun Mar 13 00:32:09 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: at.c,v 1.30 2011/08/29 14:24:03 joerg Exp $ */ +/* $NetBSD: at.c,v 1.31 2016/03/13 00:32:09 dholland Exp $ */ /* * at.c : Put file into atrun queue @@ -57,7 +57,6 @@ #include "perm.h" #include "pathnames.h" #include "stime.h" -#define MAIN #include "privs.h" /* Macros */ @@ -72,7 +71,7 @@ enum { ATQ, ATRM, AT, BATCH, CAT }; /* w #if 0 static char rcsid[] = "$OpenBSD: at.c,v 1.15 1998/06/03 16:20:26 deraadt Exp $"; #else -__RCSID("$NetBSD: at.c,v 1.30 2011/08/29 14:24:03 joerg Exp $"); +__RCSID("$NetBSD: at.c,v 1.31 2016/03/13 00:32:09 dholland Exp $"); #endif #endif @@ -108,9 +107,9 @@ sigc(int signo) /* If a signal interrupts us, remove the spool file and exit. */ if (fcreated) { - PRIV_START; + privs_enter(); (void)unlink(atfile); - PRIV_END; + privs_exit(); } (void)raise_default_signal(signo); exit(EXIT_FAILURE); @@ -207,7 +206,7 @@ writefile(time_t runtimer, unsigned char * to make sure we're alone when doing this. */ - PRIV_START; + privs_enter(); if ((lockdes = open(_PATH_LOCKFILE, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR)) < 0) perr("Cannot open lockfile " _PATH_LOCKFILE); @@ -260,7 +259,7 @@ writefile(time_t runtimer, unsigned char if (fchown(fd2, real_uid, real_gid) == -1) perr("Cannot give away file"); - PRIV_END; + privs_exit(); /* * We've successfully created the file; let's set the flag so it @@ -402,7 +401,7 @@ writefile(time_t runtimer, unsigned char (void)fclose(fp); - PRIV_START; + privs_enter(); /* * Set the x bit so that we're ready to start executing @@ -410,7 +409,7 @@ writefile(time_t runtimer, unsigned char if (fchmod(fd2, S_IRUSR | S_IWUSR | S_IXUSR) == -1) perr("Cannot give away file"); - PRIV_END; + privs_exit(); (void)close(fd2); (void)fprintf(stderr, @@ -436,7 +435,7 @@ list_jobs(void) char timestr[TIMESIZE]; int first = 1; - PRIV_START; + privs_enter(); if (chdir(_PATH_ATJOBS) == -1) perr("Cannot change to " _PATH_ATJOBS); @@ -493,7 +492,7 @@ list_jobs(void) jobno); } (void)closedir(spool); - PRIV_END; + privs_exit(); } static void @@ -508,7 +507,7 @@ process_jobs(int argc, char **argv, int unsigned char queue; int jobno; - PRIV_START; + privs_enter(); if (chdir(_PATH_ATJOBS) == -1) perr("Cannot change to " _PATH_ATJOBS); @@ -516,15 +515,15 @@ process_jobs(int argc, char **argv, int if ((spool = opendir(".")) == NULL) perr("Cannot open " _PATH_ATJOBS); - PRIV_END; + privs_exit(); /* Loop over every file in the directory */ while((dirent = readdir(spool)) != NULL) { - PRIV_START; + privs_enter(); if (stat(dirent->d_name, &buf) == -1) perr("Cannot stat in " _PATH_ATJOBS); - PRIV_END; + privs_exit(); if (sscanf(dirent->d_name, "%c%5x%8lx", &queue, &jobno, &ctm) !=3) continue; @@ -537,23 +536,23 @@ process_jobs(int argc, char **argv, int switch (what) { case ATRM: - PRIV_START; + privs_enter(); if (unlink(dirent->d_name) == -1) perr(dirent->d_name); - PRIV_END; + privs_exit(); break; case CAT: { FILE *fp; int ch; - PRIV_START; + privs_enter(); fp = fopen(dirent->d_name, "r"); - PRIV_END; + privs_exit(); if (!fp) perr("Cannot open file"); @@ -593,7 +592,7 @@ main(int argc, char **argv) int disp_version = 0; time_t timer; - RELINQUISH_PRIVS; + privs_relinquish(); /* Eat any leading paths */ if ((pgm = strrchr(argv[0], '/')) == NULL) Index: src/usr.bin/at/panic.c diff -u src/usr.bin/at/panic.c:1.13 src/usr.bin/at/panic.c:1.14 --- src/usr.bin/at/panic.c:1.13 Sat Apr 5 16:26:57 2008 +++ src/usr.bin/at/panic.c Sun Mar 13 00:32:09 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: panic.c,v 1.13 2008/04/05 16:26:57 christos Exp $ */ +/* $NetBSD: panic.c,v 1.14 2016/03/13 00:32:09 dholland Exp $ */ /* * panic.c - terminate fast in case of error @@ -46,7 +46,7 @@ #if 0 static char rcsid[] = "$OpenBSD: panic.c,v 1.4 1997/03/01 23:40:09 millert Exp $"; #else -__RCSID("$NetBSD: panic.c,v 1.13 2008/04/05 16:26:57 christos Exp $"); +__RCSID("$NetBSD: panic.c,v 1.14 2016/03/13 00:32:09 dholland Exp $"); #endif #endif @@ -61,9 +61,9 @@ panic(const char *a) * Something fatal has happened, print error message and exit. */ if (fcreated) { - PRIV_START; + privs_enter(); (void)unlink(atfile); - PRIV_END; + privs_exit(); } errx(EXIT_FAILURE, "%s", a); } @@ -78,15 +78,22 @@ perr(const char *a) */ perror(a); if (fcreated) { - PRIV_START; + privs_enter(); (void)unlink(atfile); - PRIV_END; + privs_exit(); } exit(EXIT_FAILURE); } __dead void +privs_fail(const char *msg) +{ + perr(msg); +} + +__dead +void usage(void) { Index: src/usr.bin/at/perm.c diff -u src/usr.bin/at/perm.c:1.3 src/usr.bin/at/perm.c:1.4 --- src/usr.bin/at/perm.c:1.3 Sat Apr 5 16:26:57 2008 +++ src/usr.bin/at/perm.c Sun Mar 13 00:32:09 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: perm.c,v 1.3 2008/04/05 16:26:57 christos Exp $ */ +/* $NetBSD: perm.c,v 1.4 2016/03/13 00:32:09 dholland Exp $ */ /* * perm.c - check user permission for at(1) @@ -51,7 +51,7 @@ #if 0 static char rcsid[] = "$OpenBSD: perm.c,v 1.1 1997/03/01 23:40:12 millert Exp $"; #else -__RCSID("$NetBSD: perm.c,v 1.3 2008/04/05 16:26:57 christos Exp $"); +__RCSID("$NetBSD: perm.c,v 1.4 2016/03/13 00:32:09 dholland Exp $"); #endif #endif @@ -96,20 +96,20 @@ check_permission(void) exit(EXIT_FAILURE); } - PRIV_START; + privs_enter(); fp = fopen(_PATH_AT_ALLOW, "r"); - PRIV_END; + privs_exit(); if (fp != NULL) { return check_for_user(fp, pentry->pw_name); } else { - PRIV_START; + privs_enter(); fp = fopen(_PATH_AT_DENY, "r"); - PRIV_END; + privs_exit(); if (fp != NULL) return !check_for_user(fp, pentry->pw_name); Index: src/usr.bin/at/privs.h diff -u src/usr.bin/at/privs.h:1.8 src/usr.bin/at/privs.h:1.9 --- src/usr.bin/at/privs.h:1.8 Sat Apr 5 16:26:57 2008 +++ src/usr.bin/at/privs.h Sun Mar 13 00:32:09 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: privs.h,v 1.8 2008/04/05 16:26:57 christos Exp $ */ +/* $NetBSD: privs.h,v 1.9 2016/03/13 00:32:09 dholland Exp $ */ /* * privs.h - header for privileged operations @@ -30,9 +30,8 @@ #ifndef _PRIVS_H_ #define _PRIVS_H_ -#include <unistd.h> - -/* Relinquish privileges temporarily for a setuid or setgid program +/* + * Relinquish privileges temporarily for a setuid or setgid program * with the option of getting them back later. This is done by * using POSIX saved user and groups ids. Call RELINQUISH_PRIVS once * at the beginning of the main program. This will cause all operations @@ -57,44 +56,16 @@ * to the real userid before calling any of them. */ -#ifndef MAIN -extern -#endif -uid_t real_uid, effective_uid; - -#ifndef MAIN -extern -#endif -gid_t real_gid, effective_gid; - -#define RELINQUISH_PRIVS do { \ - real_uid = getuid(); \ - effective_uid = geteuid(); \ - real_gid = getgid(); \ - effective_gid = getegid(); \ - PRIV_END; \ -} while (/*CONSTCOND*/ 0) - -#define RELINQUISH_PRIVS_ROOT(a, b) do { \ - real_uid = (a); \ - effective_uid = geteuid(); \ - real_gid = (b); \ - effective_gid = getegid(); \ - PRIV_END; \ -} while (/*CONSTCOND*/ 0) - -#define PRIV_START do { \ - if (seteuid(effective_uid) == -1) \ - perr("Cannot get user privs"); \ - if (setegid(effective_gid) == -1) \ - perr("Cannot get group privs"); \ -} while (/*CONSTCOND*/ 0) - -#define PRIV_END do { \ - if (setegid(real_gid) == -1) \ - perr("Cannot relinguish group privs"); \ - if (seteuid(real_uid) == -1) \ - perr("Cannot relinguish user privs"); \ -} while (/*CONSTCOND*/ 0) +extern uid_t real_uid, effective_uid; +extern gid_t real_gid, effective_gid; + +void privs_relinquish(void); +void privs_relinquish_root(uid_t ruid, gid_t rgid); + +void privs_enter(void); +void privs_exit(void); + +/* caller provides this */ +__dead void privs_fail(const char *msg); #endif /* _PRIV_H_ */ Added files: Index: src/usr.bin/at/privs.c diff -u /dev/null src/usr.bin/at/privs.c:1.1 --- /dev/null Sun Mar 13 00:32:09 2016 +++ src/usr.bin/at/privs.c Sun Mar 13 00:32:09 2016 @@ -0,0 +1,99 @@ +/* $NetBSD: privs.c,v 1.1 2016/03/13 00:32:09 dholland Exp $ */ + +/* + * privs.c - privileged operations + * Copyright (C) 1993 Thomas Koenig + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author(s) may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * From: OpenBSD: privs.h,v 1.4 1997/03/01 23:40:12 millert Exp + */ + +#include <unistd.h> + +#include "privs.h" + +/* + * Relinquish privileges temporarily for a setuid or setgid program + * with the option of getting them back later. This is done by + * using POSIX saved user and groups ids. Call RELINQUISH_PRIVS once + * at the beginning of the main program. This will cause all operations + * to be executed with the real userid. When you need the privileges + * of the setuid/setgid invocation, call PRIV_START; when you no longer + * need it, call PRIV_END. Note that it is an error to call PRIV_START + * and not PRIV_END within the same function. + * + * Use RELINQUISH_PRIVS_ROOT(a,b) if your program started out running + * as root, and you want to drop back the effective userid to a + * and the effective group id to b, with the option to get them back + * later. + * + * Problems: Do not use return between PRIV_START and PRIV_END; this + * will cause the program to continue running in an unprivileged + * state. + * + * It is NOT safe to call exec(), system() or popen() with a user- + * supplied program (i.e. without carefully checking PATH and any + * library load paths) with relinquished privileges; the called program + * can acquire them just as easily. Set both effective and real userid + * to the real userid before calling any of them. + */ + +uid_t real_uid, effective_uid; +gid_t real_gid, effective_gid; + +void +privs_enter(void) +{ + if (seteuid(effective_uid) == -1) + privs_fail("Cannot get user privs"); + if (setegid(effective_gid) == -1) + privs_fail("Cannot get group privs"); +} + +void +privs_exit(void) +{ + if (setegid(real_gid) == -1) + privs_fail("Cannot relinguish group privs"); + if (seteuid(real_uid) == -1) + privs_fail("Cannot relinguish user privs"); +} + +void +privs_relinquish(void) +{ + real_uid = getuid(); + effective_uid = geteuid(); + real_gid = getgid(); + effective_gid = getegid(); + privs_exit(); +} + +void +privs_relinquish_root(uid_t ruid, gid_t rgid) +{ + real_uid = ruid; + real_gid = rgid; + effective_uid = geteuid(); + effective_gid = getegid(); + privs_exit(); +}