[CRIU] [PATCH] security: set suid flag on crtools and check real uid on dump/restore

Ruslan Kuprieiev kupruser at gmail.com
Wed Oct 2 06:00:48 PDT 2013


Hi!

Lets set suid flag on crtools, so non-root users could dump/restore 
their own tasks and start service for their own tasks. On start criu 
will get it's real uid and will allow user to dump/restore only tasks 
that he own.

Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
-------------- next part --------------
---
diff --git a/Makefile b/Makefile
index 0834277..8c75e92 100644
--- a/Makefile
+++ b/Makefile
@@ -166,6 +166,7 @@ PROGRAM-BUILTINS	+= $(ARCH_DIR)/vdso-pie.o
 $(PROGRAM): $(SYSCALL-LIB) $(ARCH-LIB) $(PROGRAM-BUILTINS)
 	$(E) "  LINK    " $@
 	$(Q) $(CC) $(CFLAGS) $^ $(LIBS) $(LDFLAGS) -o $@
+	$(Q) chmod u+s $@
 
 zdtm: all
 	$(Q) $(MAKE) -C test/zdtm all
diff --git a/cr-restore.c b/cr-restore.c
index 3debcbe..8c7389c 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1957,6 +1957,9 @@ static int prepare_creds(int pid, struct task_restore_core_args *args)
 		return -1;
 	}
 
+	if (!may_restore_uid(ce->uid))
+		return -1;
+
 	args->creds = *ce;
 	args->creds.cap_inh = args->cap_inh;
 	memcpy(args->cap_inh, ce->cap_inh, sizeof(args->cap_inh));
diff --git a/cr-service.c b/cr-service.c
index d1286c3..38543e7 100644
--- a/cr-service.c
+++ b/cr-service.c
@@ -87,7 +87,8 @@ static int setup_dump_from_req(int sk, CriuDumpReq *req)
 		return -1;
 	}
 
-	restrict_uid(ids.uid);
+	if (restrict_uid(ids.uid) < 0)
+		return -1;
 
 	if (fstat(sk, &st)) {
 		pr_perror("Can't get socket stat");
diff --git a/crtools.c b/crtools.c
index ebab052..83948e9 100644
--- a/crtools.c
+++ b/crtools.c
@@ -72,6 +72,7 @@ int main(int argc, char *argv[])
 	BUILD_BUG_ON(PAGE_SIZE != PAGE_IMAGE_SIZE);
 
 	cr_pb_init();
+	security_init();
 
 	if (argc < 2)
 		goto usage;
diff --git a/include/crtools.h b/include/crtools.h
index 8f84f94..b197a40 100644
--- a/include/crtools.h
+++ b/include/crtools.h
@@ -208,7 +208,9 @@ static inline bool pid_rst_prio(unsigned pid_a, unsigned pid_b)
 	return pid_a < pid_b;
 }
 
-void restrict_uid(unsigned int uid);
+void security_init(void);
+int restrict_uid(unsigned int uid);
 bool may_dump_uid(unsigned int uid);
+bool may_restore_uid(unsigned int uid);
 
 #endif /* __CR_CRTOOLS_H__ */
diff --git a/security.c b/security.c
index caf9dda..40e4b59 100644
--- a/security.c
+++ b/security.c
@@ -2,7 +2,8 @@
 #include "crtools.h"
 #include "log.h"
 
-static unsigned int dumper_uid = 0;
+static unsigned int cr_uid; /* "Effective" uid, which is used in C/R */
+static unsigned int ruid; /* Real uid of the user, which runs criu */
 
 /*
  * Setup what user is requesting for dump (via rpc or using 
@@ -11,19 +12,56 @@ static unsigned int dumper_uid = 0;
  * access to. (Or implement some trickier security policy).
  */
 
-void restrict_uid(unsigned int uid)
+void security_init()
 {
-	pr_info("Restrict C/R with %u uid\n", uid);
-	dumper_uid = uid;
+	ruid = getuid();
+	cr_uid = ruid;
 }
 
-bool may_dump_uid(unsigned int uid)
+int restrict_uid(unsigned int uid)
+{
+	if (ruid == 0) {
+		pr_info("Restrict C/R with %u uid\n", uid);
+		cr_uid = uid;
+		return 0;
+	}
+	if (cr_uid == uid) {
+		pr_info("C/R is already restricted with %u uid\n", uid);
+		return 0;
+	}
+
+	pr_perror("User(%u uid) has no right to restrict C/R with %u uid\n",
+								ruid, uid);
+	return -1;
+}
+
+
+static bool check_uid(unsigned int uid)
 {
-	if (dumper_uid == 0)
+	if (cr_uid == 0)
 		return true;
-	if (dumper_uid == uid)
+	if (cr_uid == uid)
 		return true;
 
-	pr_err("UID (%u) != dumper's UID(%u)\n", uid, dumper_uid);
 	return false;
 }
+
+bool may_dump_uid(unsigned int uid)
+{
+	if (!check_uid(uid)) {
+		pr_err("UID (%u) != dumper's UID(%u)\n", uid, cr_uid);
+		return false;
+	}
+
+	return true;
+}
+
+bool may_restore_uid(unsigned int uid)
+{
+	if (!check_uid(uid)) {
+		pr_err("UID (%u) != restorer's UID(%u)\n", uid, cr_uid);
+		return false;
+	}
+
+	return true;
+}


More information about the CRIU mailing list