diff -ruN shadow-4.2.1/libmisc/idmapping.c shadow-4.2.1.new/libmisc/idmapping.c --- shadow-4.2.1/libmisc/idmapping.c 2014-03-01 19:59:51.000000000 +0100 +++ shadow-4.2.1.new/libmisc/idmapping.c 2016-07-19 10:55:49.339097323 +0200 @@ -77,6 +77,11 @@ return NULL; if (!getulong(argv[argidx + 2], &mapping->count)) return NULL; + + if (ULONG_MAX - mapping->upper <= mapping->count || ULONG_MAX - mapping->lower <= mapping->count) { + fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog); + exit(EXIT_FAILURE); + } } return mappings; } diff -ruN shadow-4.2.1/libmisc/myname.c shadow-4.2.1.new/libmisc/myname.c --- shadow-4.2.1/libmisc/myname.c 2014-03-01 19:59:51.000000000 +0100 +++ shadow-4.2.1.new/libmisc/myname.c 2016-07-19 10:14:49.298852058 +0200 @@ -44,25 +44,13 @@ /*@null@*/ /*@only@*/struct passwd *get_my_pwent (void) { struct passwd *pw; - const char *cp = getlogin (); uid_t ruid = getuid (); - /* - * Try getlogin() first - if it fails or returns a non-existent - * username, or a username which doesn't match the real UID, fall - * back to getpwuid(getuid()). This should work reasonably with - * usernames longer than the utmp limit (8 characters), as well as - * shared UIDs - but not both at the same time... + /* Do not use getlogin(). Its not suitable for suid binaries. * * XXX - when running from su, will return the current user (not * the original user, like getlogin() does). Does this matter? */ - if ((NULL != cp) && ('\0' != *cp)) { - pw = xgetpwnam (cp); - if ((NULL != pw) && (pw->pw_uid == ruid)) { - return pw; - } - } return xgetpwuid (ruid); } diff -ruN shadow-4.2.1/lib/getulong.c shadow-4.2.1.new/lib/getulong.c --- shadow-4.2.1/lib/getulong.c 2014-03-01 18:50:05.000000000 +0100 +++ shadow-4.2.1.new/lib/getulong.c 2016-07-19 10:36:14.476785123 +0200 @@ -44,22 +44,19 @@ */ int getulong (const char *numstr, /*@out@*/unsigned long int *result) { - long long int val; + unsigned long int val; char *endptr; errno = 0; - val = strtoll (numstr, &endptr, 0); + val = strtoul (numstr, &endptr, 0); if ( ('\0' == *numstr) || ('\0' != *endptr) || (ERANGE == errno) - /*@+ignoresigns@*/ - || (val != (unsigned long int)val) - /*@=ignoresigns@*/ ) { return 0; } - *result = (unsigned long int)val; + *result = val; return 1; }