Changeset View
Standalone View
lib/libutil/login_class.c
Show All 31 Lines | |||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <login_cap.h> | #include <login_cap.h> | ||||
#include <paths.h> | #include <paths.h> | ||||
#include <pwd.h> | #include <pwd.h> | ||||
#include <stdint.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <syslog.h> | #include <syslog.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
static struct login_res { | static struct login_res { | ||||
▲ Show 20 Lines • Show All 331 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* Private function which takes care of processing | * Private function which takes care of processing | ||||
*/ | */ | ||||
static mode_t | static void | ||||
setlogincontext(login_cap_t *lc, const struct passwd *pwd, | setlogincontext(login_cap_t *lc, const struct passwd *pwd, unsigned long flags) | ||||
mode_t mymask, unsigned long flags) | |||||
{ | { | ||||
if (lc) { | if (lc) { | ||||
/* Set resources */ | /* Set resources */ | ||||
if (flags & LOGIN_SETRESOURCES) | if (flags & LOGIN_SETRESOURCES) | ||||
setclassresources(lc); | setclassresources(lc); | ||||
/* See if there's a umask override */ | /* See if there's a umask override */ | ||||
if (flags & LOGIN_SETUMASK) | if (flags & LOGIN_SETUMASK) { | ||||
mymask = (mode_t)login_getcapnum(lc, "umask", mymask, mymask); | /* | ||||
* Make it unlikely that someone would input our default sentinel | |||||
* indicating no specification. | |||||
*/ | |||||
emaste: Hrm, `login_getcapnum` has a somewhat unfortunate interface. | |||||
Done Inline ActionsYes... Ideally, the libutil interfaces should be revised, but this public interface has been there for so long that it also means reviewing and changing all the applications using it. Not sure how big of a job this is. Just wanted to avoid it as much as possible for this series. olce: Yes... Ideally, the `libutil` interfaces should be revised, but this public interface has been… | |||||
const rlim_t def_val = INT64_MIN + 1, err_val = INT64_MIN; | |||||
const rlim_t val = login_getcapnum(lc, "umask", def_val, err_val); | |||||
if (val != def_val) { | |||||
if (val < 0 || val > UINT16_MAX) { | |||||
Done Inline ActionsPerhaps adding || val == err_val does not change the generated code and does not generate a warning? That might be more clear than the comment. emaste: Perhaps adding `|| val == err_val` does not change the generated code and does not generate a… | |||||
Done Inline ActionsAdding it doesn't change the produced assembly. That said, I find this test strange since it is redundant, which presses me to add a comment about that... So, since in both cases I'm putting a comment, I think I still prefer to forget about the redundant construct. olce: Adding it doesn't change the produced assembly. That said, I find this test strange since it… | |||||
/* We get here also on 'err_val'. */ | |||||
syslog(LOG_WARNING, | |||||
Done Inline ActionsThe indent looks wrong, it should be +4 spaces from the previous line. kib: The indent looks wrong, it should be +4 spaces from the previous line. | |||||
Done Inline ActionsRight. Fixing this. olce: Right. Fixing this. | |||||
"%s%s%sLogin class '%s': " | |||||
"Invalid umask specification: '%s'", | |||||
pwd ? "Login '" : "", | |||||
pwd ? pwd->pw_name : "", | |||||
pwd ? "': " : "", | |||||
lc->lc_class, | |||||
login_getcapstr(lc, "umask", "", "")); | |||||
} else { | |||||
Done Inline ActionsSuggest { } around the first block, even though it is only one statement it is wrapped over many lines. (Even if not wrapped over many lines I think it's preferable to use braces on all blocks of an if-else if any do.) if (x) { one_statement(); } else { a_lot(); of_stuff(); over_here(); } emaste: Suggest `{` `}` around the first block, even though it is only one statement it is wrapped over… | |||||
const mode_t mode = val; | |||||
umask(mode); | |||||
} | |||||
} | |||||
} | |||||
/* Set paths */ | /* Set paths */ | ||||
if (flags & LOGIN_SETPATH) | if (flags & LOGIN_SETPATH) | ||||
setclassenvironment(lc, pwd, 1); | setclassenvironment(lc, pwd, 1); | ||||
/* Set environment */ | /* Set environment */ | ||||
if (flags & LOGIN_SETENV) | if (flags & LOGIN_SETENV) | ||||
setclassenvironment(lc, pwd, 0); | setclassenvironment(lc, pwd, 0); | ||||
/* Set cpu affinity */ | /* Set cpu affinity */ | ||||
if (flags & LOGIN_SETCPUMASK) | if (flags & LOGIN_SETCPUMASK) | ||||
setclasscpumask(lc); | setclasscpumask(lc); | ||||
} | } | ||||
return (mymask); | |||||
} | } | ||||
/* | /* | ||||
* setusercontext() | * setusercontext() | ||||
* | * | ||||
* Given a login class <lc> and a user in <pwd>, with a uid <uid>, | * Given a login class <lc> and a user in <pwd>, with a uid <uid>, | ||||
* set the context as in setclasscontext(). <flags> controls which | * set the context as in setclasscontext(). <flags> controls which | ||||
* values are set. | * values are set. | ||||
* | * | ||||
* The difference between setclasscontext() and setusercontext() is | * The difference between setclasscontext() and setusercontext() is | ||||
* that the former sets things up for an already-existing process, | * that the former sets things up for an already-existing process, | ||||
* while the latter sets things up from a root context. Such as might | * while the latter sets things up from a root context. Such as might | ||||
* be called from login(1). | * be called from login(1). | ||||
* | * | ||||
*/ | */ | ||||
int | int | ||||
setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned int flags) | setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned int flags) | ||||
{ | { | ||||
rlim_t p; | rlim_t p; | ||||
mode_t mymask; | |||||
login_cap_t *llc = NULL; | login_cap_t *llc = NULL; | ||||
struct rtprio rtp; | struct rtprio rtp; | ||||
int error; | int error; | ||||
if (lc == NULL) { | if (lc == NULL) { | ||||
if (pwd != NULL && (lc = login_getpwclass(pwd)) != NULL) | if (pwd != NULL && (lc = login_getpwclass(pwd)) != NULL) | ||||
llc = lc; /* free this when we're done */ | llc = lc; /* free this when we're done */ | ||||
} | } | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | if (error != 0) { | ||||
syslog(LOG_ERR, "setloginclass(%s): %m", lc->lc_class); | syslog(LOG_ERR, "setloginclass(%s): %m", lc->lc_class); | ||||
#ifdef notyet | #ifdef notyet | ||||
login_close(llc); | login_close(llc); | ||||
return (-1); | return (-1); | ||||
#endif | #endif | ||||
} | } | ||||
} | } | ||||
mymask = (flags & LOGIN_SETUMASK) ? umask(LOGIN_DEFUMASK) : 0; | setlogincontext(lc, pwd, flags); | ||||
mymask = setlogincontext(lc, pwd, mymask, flags); | |||||
login_close(llc); | login_close(llc); | ||||
/* This needs to be done after anything that needs root privs */ | /* This needs to be done after anything that needs root privs */ | ||||
if ((flags & LOGIN_SETUSER) && setuid(uid) != 0) { | if ((flags & LOGIN_SETUSER) && setuid(uid) != 0) { | ||||
syslog(LOG_ERR, "setuid(%lu): %m", (u_long)uid); | syslog(LOG_ERR, "setuid(%lu): %m", (u_long)uid); | ||||
return (-1); /* Paranoia again */ | return (-1); /* Paranoia again */ | ||||
} | } | ||||
/* | /* | ||||
* Now, we repeat some of the above for the user's private entries | * Now, we repeat some of the above for the user's private entries | ||||
*/ | */ | ||||
if (geteuid() == uid && (lc = login_getuserclass(pwd)) != NULL) { | if (geteuid() == uid && (lc = login_getuserclass(pwd)) != NULL) { | ||||
mymask = setlogincontext(lc, pwd, mymask, flags); | setlogincontext(lc, pwd, flags); | ||||
login_close(lc); | login_close(lc); | ||||
} | } | ||||
/* Finally, set any umask we've found */ | |||||
if (flags & LOGIN_SETUMASK) | |||||
umask(mymask); | |||||
return (0); | return (0); | ||||
} | } |
Hrm, login_getcapnum has a somewhat unfortunate interface.