diff options
Diffstat (limited to '')
-rw-r--r-- | lib/limits.c (renamed from libmisc/limits.c) | 138 |
1 files changed, 43 insertions, 95 deletions
diff --git a/libmisc/limits.c b/lib/limits.c index fea85fe..813c082 100644 --- a/libmisc/limits.c +++ b/lib/limits.c @@ -28,11 +28,12 @@ #include <pwd.h> #include "getdef.h" #include "shadowlog.h" -#ifdef HAVE_SYS_RESOURCE_H #include <sys/resource.h> -#define LIMITS -#endif -#ifdef LIMITS + +#include "atoi/str2i.h" +#include "memzero.h" + + #ifndef LIMITS_FILE #define LIMITS_FILE "/etc/limits" #endif @@ -48,8 +49,10 @@ static int setrlimit_value (unsigned int resource, const char *value, unsigned int multiplier) { - struct rlimit rlim; - rlim_t limit; + char *end; + long l; + rlim_t limit; + struct rlimit rlim; /* The "-" is special, not belonging to a strange negative limit. * It is infinity, in a controlled way. @@ -58,23 +61,18 @@ static int setrlimit_value (unsigned int resource, limit = RLIM_INFINITY; } else { - /* We cannot use getlong here because it fails when there + /* We cannot use str2sl() here because it fails when there * is more to the value than just this number! * Also, we are limited to base 10 here (hex numbers will not * work with the limit string parser as is anyway) */ - char *endptr; - long longlimit = strtol (value, &endptr, 10); - if ((0 == longlimit) && (value == endptr)) { - /* No argument at all. No-op. - * FIXME: We could instead throw an error, though. - */ - return 0; - } - longlimit *= multiplier; - limit = (rlim_t)longlimit; - if (longlimit != limit) - { + errno = 0; + l = strtol(value, &end, 10); + + if (value == end || errno != 0) + return 0; // FIXME: We could instead throw an error, though. + + if (__builtin_mul_overflow(l, multiplier, &limit)) { /* FIXME: Again, silent error handling... * Wouldn't screaming make more sense? */ @@ -95,11 +93,11 @@ static int set_prio (const char *value) { long prio; - if ( (getlong (value, &prio) == 0) + if ( (str2sl(&prio, value) == -1) || (prio != (int) prio)) { return 0; } - if (setpriority (PRIO_PROCESS, 0, (int) prio) != 0) { + if (setpriority (PRIO_PROCESS, 0, prio) != 0) { return LOGIN_ERROR_RLIMIT; } return 0; @@ -108,14 +106,14 @@ static int set_prio (const char *value) static int set_umask (const char *value) { - unsigned long int mask; + unsigned long mask; - if ( (getulong (value, &mask) == 0) + if ( (str2ul(&mask, value) == -1) || (mask != (mode_t) mask)) { return 0; } - (void) umask ((mode_t) mask); + (void) umask (mask); return 0; } @@ -123,14 +121,9 @@ static int set_umask (const char *value) /* Counts the number of user logins and check against the limit */ static int check_logins (const char *name, const char *maxlogins) { -#ifdef USE_UTMPX - struct utmpx *ut; -#else /* !USE_UTMPX */ - struct utmp *ut; -#endif /* !USE_UTMPX */ unsigned long limit, count; - if (getulong (maxlogins, &limit) == 0) { + if (str2ul(&limit, maxlogins) == -1) { return 0; } @@ -139,38 +132,8 @@ static int check_logins (const char *name, const char *maxlogins) return LOGIN_ERROR_LOGIN; } - count = 0; -#ifdef USE_UTMPX - setutxent (); - while ((ut = getutxent ())) -#else /* !USE_UTMPX */ - setutent (); - while ((ut = getutent ())) -#endif /* !USE_UTMPX */ - { - if (USER_PROCESS != ut->ut_type) { - continue; - } - if ('\0' == ut->ut_user[0]) { - continue; - } - if (strncmp (name, ut->ut_user, sizeof (ut->ut_user)) != 0) { - continue; - } - count++; - if (count > limit) { - break; - } - } -#ifdef USE_UTMPX - endutxent (); -#else /* !USE_UTMPX */ - endutent (); -#endif /* !USE_UTMPX */ - /* - * This is called after setutmp(), so the number of logins counted - * includes the user who is currently trying to log in. - */ + count = active_sessions_count(name, limit); + if (count > limit) { SYSLOG ((LOG_WARN, "Too many logins (max %lu) for %s\n", @@ -243,34 +206,26 @@ static int do_user_limits (const char *buf, const char *name) while ('\0' != *pp) { switch (*pp++) { -#ifdef RLIMIT_AS case 'a': case 'A': /* RLIMIT_AS - max address space (KB) */ retval |= setrlimit_value (RLIMIT_AS, pp, 1024); break; -#endif -#ifdef RLIMIT_CORE case 'c': case 'C': /* RLIMIT_CORE - max core file size (KB) */ retval |= setrlimit_value (RLIMIT_CORE, pp, 1024); break; -#endif -#ifdef RLIMIT_DATA case 'd': case 'D': /* RLIMIT_DATA - max data size (KB) */ retval |= setrlimit_value (RLIMIT_DATA, pp, 1024); break; -#endif -#ifdef RLIMIT_FSIZE case 'f': case 'F': /* RLIMIT_FSIZE - Maximum filesize (KB) */ retval |= setrlimit_value (RLIMIT_FSIZE, pp, 1024); break; -#endif #ifdef RLIMIT_NICE case 'i': case 'I': @@ -294,13 +249,11 @@ static int do_user_limits (const char *buf, const char *name) retval |= setrlimit_value (RLIMIT_MEMLOCK, pp, 1024); break; #endif -#ifdef RLIMIT_NOFILE case 'n': case 'N': /* RLIMIT_NOFILE - max number of open files */ retval |= setrlimit_value (RLIMIT_NOFILE, pp, 1); break; -#endif #ifdef RLIMIT_RTPRIO case 'o': case 'O': @@ -319,20 +272,16 @@ static int do_user_limits (const char *buf, const char *name) retval |= setrlimit_value (RLIMIT_RSS, pp, 1024); break; #endif -#ifdef RLIMIT_STACK case 's': case 'S': /* RLIMIT_STACK - max stack size (KB) */ retval |= setrlimit_value (RLIMIT_STACK, pp, 1024); break; -#endif -#ifdef RLIMIT_CPU case 't': case 'T': /* RLIMIT_CPU - max CPU time (MIN) */ retval |= setrlimit_value (RLIMIT_CPU, pp, 60); break; -#endif #ifdef RLIMIT_NPROC case 'u': case 'U': @@ -409,11 +358,11 @@ static int setup_user_limits (const char *uname) char tempbuf[1024]; /* init things */ - memzero (buf, sizeof (buf)); - memzero (name, sizeof (name)); - memzero (limits, sizeof (limits)); - memzero (deflimits, sizeof (deflimits)); - memzero (tempbuf, sizeof (tempbuf)); + MEMZERO(buf); + MEMZERO(name); + MEMZERO(limits); + MEMZERO(deflimits); + MEMZERO(tempbuf); /* start the checks */ fil = fopen (LIMITS_FILE, "r"); @@ -430,7 +379,7 @@ static int setup_user_limits (const char *uname) if (('#' == buf[0]) || ('\n' == buf[0])) { continue; } - memzero (tempbuf, sizeof (tempbuf)); + MEMZERO(tempbuf); /* a valid line should have a username, then spaces, * then limits * we allow the format: @@ -479,7 +428,6 @@ static int setup_user_limits (const char *uname) } return do_user_limits (limits, uname); } -#endif /* LIMITS */ static void setup_usergroups (const struct passwd *info) @@ -523,7 +471,6 @@ void setup_limits (const struct passwd *info) */ if (getdef_bool ("QUOTAS_ENAB")) { -#ifdef LIMITS if (info->pw_uid != 0) { if ((setup_user_limits (info->pw_name) & LOGIN_ERROR_LOGIN) != 0) { (void) fputs (_("Too many logins.\n"), log_get_logfd()); @@ -531,18 +478,18 @@ void setup_limits (const struct passwd *info) exit (EXIT_FAILURE); } } -#endif for (cp = info->pw_gecos; cp != NULL; cp = strchr (cp, ',')) { if (',' == *cp) { cp++; } if (strncmp (cp, "pri=", 4) == 0) { - long int inc; - if ( (getlong (cp + 4, &inc) == 1) + long inc; + + if ( (str2sl(&inc, cp + 4) == 0) && (inc >= -20) && (inc <= 20)) { errno = 0; - if ( (nice ((int) inc) != -1) + if ( (nice (inc) != -1) || (0 != errno)) { continue; } @@ -556,10 +503,10 @@ void setup_limits (const struct passwd *info) continue; } if (strncmp (cp, "ulimit=", 7) == 0) { - long int blocks; - if ( (getlong (cp + 7, &blocks) == 0) + long blocks; + if ( (str2sl(&blocks, cp + 7) == -1) || (blocks != (int) blocks) - || (set_filesize_limit ((int) blocks) != 0)) { + || (set_filesize_limit (blocks) != 0)) { SYSLOG ((LOG_WARN, "Can't set the ulimit for user %s", info->pw_name)); @@ -567,14 +514,15 @@ void setup_limits (const struct passwd *info) continue; } if (strncmp (cp, "umask=", 6) == 0) { - unsigned long int mask; - if ( (getulong (cp + 6, &mask) == 0) + unsigned long mask; + + if ( (str2ul(&mask, cp + 6) == -1) || (mask != (mode_t) mask)) { SYSLOG ((LOG_WARN, "Can't set umask value for user %s", info->pw_name)); } else { - (void) umask ((mode_t) mask); + (void) umask (mask); } continue; @@ -584,6 +532,6 @@ void setup_limits (const struct passwd *info) } #else /* !USE_PAM */ -extern int errno; /* warning: ANSI C forbids an empty source file */ +extern int ISO_C_forbids_an_empty_translation_unit; #endif /* !USE_PAM */ |