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;
 }