109 lines
3.3 KiB
Diff
109 lines
3.3 KiB
Diff
|
From fd4405b763d26649339069532e79bd45013c8c38 Mon Sep 17 00:00:00 2001
|
||
|
From: Tomas Mraz <tmraz@fedoraproject.org>
|
||
|
Date: Mon, 20 Jan 2020 13:58:07 +0100
|
||
|
Subject: [PATCH] Do not mistake a regular user process for a namespaced one
|
||
|
|
||
|
In case there is a regular user with a process running on a system
|
||
|
with uid falling into a namespaced uid range of another user.
|
||
|
The user with the colliding namespaced uid range will not be
|
||
|
allowed to be deleted without forcing the action with -f.
|
||
|
|
||
|
The user_busy() is adjusted to check whether the suspected process
|
||
|
is really a namespaced process in a different namespace.
|
||
|
---
|
||
|
libmisc/user_busy.c | 44 ++++++++++++++++++++++++++++++++++++--------
|
||
|
1 file changed, 36 insertions(+), 8 deletions(-)
|
||
|
|
||
|
diff --git a/libmisc/user_busy.c b/libmisc/user_busy.c
|
||
|
index b0867568..324bb946 100644
|
||
|
--- a/libmisc/user_busy.c
|
||
|
+++ b/libmisc/user_busy.c
|
||
|
@@ -39,6 +39,7 @@
|
||
|
#include <sys/types.h>
|
||
|
#include <dirent.h>
|
||
|
#include <fcntl.h>
|
||
|
+#include <unistd.h>
|
||
|
#include "defines.h"
|
||
|
#include "prototypes.h"
|
||
|
#ifdef ENABLE_SUBIDS
|
||
|
@@ -106,6 +107,31 @@ static int user_busy_utmp (const char *name)
|
||
|
#endif /* !__linux__ */
|
||
|
|
||
|
#ifdef __linux__
|
||
|
+#ifdef ENABLE_SUBIDS
|
||
|
+#define in_parentuid_range(uid) ((uid) >= parentuid && (uid) < parentuid + range)
|
||
|
+static int different_namespace (const char *sname)
|
||
|
+{
|
||
|
+ /* 41: /proc/xxxxxxxxxx/task/xxxxxxxxxx/ns/user + \0 */
|
||
|
+ char path[41];
|
||
|
+ char buf[512], buf2[512];
|
||
|
+ ssize_t llen1, llen2;
|
||
|
+
|
||
|
+ snprintf (path, 41, "/proc/%s/ns/user", sname);
|
||
|
+
|
||
|
+ if ((llen1 = readlink (path, buf, sizeof(buf))) == -1)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ if ((llen2 = readlink ("/proc/self/ns/user", buf2, sizeof(buf2))) == -1)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ if (llen1 == llen2 && memcmp (buf, buf2, llen1) == 0)
|
||
|
+ return 0; /* same namespace */
|
||
|
+
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+#endif /* ENABLE_SUBIDS */
|
||
|
+
|
||
|
+
|
||
|
static int check_status (const char *name, const char *sname, uid_t uid)
|
||
|
{
|
||
|
/* 40: /proc/xxxxxxxxxx/task/xxxxxxxxxx/status + \0 */
|
||
|
@@ -114,7 +140,6 @@ static int check_status (const char *name, const char *sname, uid_t uid)
|
||
|
FILE *sfile;
|
||
|
|
||
|
snprintf (status, 40, "/proc/%s/status", sname);
|
||
|
- status[39] = '\0';
|
||
|
|
||
|
sfile = fopen (status, "r");
|
||
|
if (NULL == sfile) {
|
||
|
@@ -123,26 +148,29 @@ static int check_status (const char *name, const char *sname, uid_t uid)
|
||
|
while (fgets (line, sizeof (line), sfile) == line) {
|
||
|
if (strncmp (line, "Uid:\t", 5) == 0) {
|
||
|
unsigned long ruid, euid, suid;
|
||
|
+
|
||
|
assert (uid == (unsigned long) uid);
|
||
|
+ (void) fclose (sfile);
|
||
|
if (sscanf (line,
|
||
|
"Uid:\t%lu\t%lu\t%lu\n",
|
||
|
&ruid, &euid, &suid) == 3) {
|
||
|
if ( (ruid == (unsigned long) uid)
|
||
|
|| (euid == (unsigned long) uid)
|
||
|
- || (suid == (unsigned long) uid)
|
||
|
+ || (suid == (unsigned long) uid) ) {
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
#ifdef ENABLE_SUBIDS
|
||
|
- || have_sub_uids(name, ruid, 1)
|
||
|
- || have_sub_uids(name, euid, 1)
|
||
|
- || have_sub_uids(name, suid, 1)
|
||
|
-#endif /* ENABLE_SUBIDS */
|
||
|
+ if ( different_namespace (sname)
|
||
|
+ && ( have_sub_uids(name, ruid, 1)
|
||
|
+ || have_sub_uids(name, euid, 1)
|
||
|
+ || have_sub_uids(name, suid, 1))
|
||
|
) {
|
||
|
- (void) fclose (sfile);
|
||
|
return 1;
|
||
|
}
|
||
|
+#endif /* ENABLE_SUBIDS */
|
||
|
} else {
|
||
|
/* Ignore errors. This is just a best effort. */
|
||
|
}
|
||
|
- (void) fclose (sfile);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
--
|
||
|
2.25.2
|
||
|
|