[v4,1/4] locks: Add c/r of non broken leases (kernel>=v4.1)

Submitted by Pavel Begunkov (Silence) on Sept. 9, 2017, 4:51 p.m.

Details

Message ID 20170909165140.30434-2-asml.silence@gmail.com
State Accepted
Series "file leases support"
Headers show

Commit Message

Pavel Begunkov (Silence) Sept. 9, 2017, 4:51 p.m.
Leases in breaking state are not supported. In that case criu will
report an error during the dumping. Also lock info in
/proc/<pid>/fdinfo should be presented (since kernel 4.1).

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
 criu/file-lock.c         | 34 ++++++++++++++++++++++++++++++++++
 criu/include/file-lock.h |  1 +
 criu/proc_parse.c        |  5 +++++
 3 files changed, 40 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/file-lock.c b/criu/file-lock.c
index 2d4036c75..816dbca5b 100644
--- a/criu/file-lock.c
+++ b/criu/file-lock.c
@@ -5,6 +5,7 @@ 
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/fsuid.h>
 #include <sys/sysmacros.h>
 
 #include "cr_options.h"
@@ -292,6 +293,9 @@  int note_file_lock(struct pid *pid, int fd, int lfd, struct fd_parms *p)
 			 */
 			if (fl->fl_owner != pid->real)
 				continue;
+		} else if (fl->fl_kind == FL_LEASE) {
+			pr_err("Leases are not supported for kernel <= v4.0");
+			return -1;
 		} else /* fl->fl_kind == FL_FLOCK || fl->fl_kind == FL_OFD */ {
 			int ret;
 
@@ -329,6 +333,30 @@  int note_file_lock(struct pid *pid, int fd, int lfd, struct fd_parms *p)
 	return 0;
 }
 
+static int set_file_lease(int fd, int type)
+{
+	int old_fsuid, ret;
+	struct stat st;
+
+	if (fstat(fd, &st)) {
+		pr_perror("Can't get file stat (%i)\n", fd);
+		return -1;
+	}
+
+	/*
+	 * An unprivileged process may take out a lease only if
+	 * uid of the file matches the fsuid of the process.
+	 */
+	old_fsuid = setfsuid(st.st_uid);
+
+	ret = fcntl(fd, F_SETLEASE, type);
+	if (ret < 0)
+		pr_perror("Can't set lease\n");
+
+	setfsuid(old_fsuid);
+	return ret;
+}
+
 static int restore_file_lock(FileLockEntry *fle)
 {
 	int ret = -1;
@@ -395,6 +423,12 @@  static int restore_file_lock(FileLockEntry *fle)
 			pr_err("Can not set ofd lock!\n");
 			goto err;
 		}
+	} else if (fle->flag & FL_LEASE) {
+		ret = set_file_lease(fle->fd, fle->type);
+		if (ret < 0) {
+			pr_perror("Can't set lease!\n");
+			goto err;
+		}
 	} else {
 		pr_err("Unknown file lock style!\n");
 		goto err;
diff --git a/criu/include/file-lock.h b/criu/include/file-lock.h
index c3f2dabf7..f70739adb 100644
--- a/criu/include/file-lock.h
+++ b/criu/include/file-lock.h
@@ -10,6 +10,7 @@ 
 #define FL_POSIX	1
 #define FL_FLOCK	2
 #define FL_OFD		4
+#define FL_LEASE	8
 
 /* for posix fcntl() and lockf() */
 #ifndef F_RDLCK
diff --git a/criu/proc_parse.c b/criu/proc_parse.c
index e33da8d56..d3893272c 100644
--- a/criu/proc_parse.c
+++ b/criu/proc_parse.c
@@ -1991,6 +1991,8 @@  static int parse_file_lock_buf(char *buf, struct file_lock *fl,
 		fl->fl_kind = FL_FLOCK;
 	else if (!strcmp(fl_flag, "OFDLCK"))
 		fl->fl_kind = FL_OFD;
+	else if (!strcmp(fl_flag, "LEASE"))
+		fl->fl_kind = FL_LEASE;
 	else
 		fl->fl_kind = FL_UNKNOWN;
 
@@ -2007,6 +2009,9 @@  static int parse_file_lock_buf(char *buf, struct file_lock *fl,
 			pr_err("Unknown lock option!\n");
 			return -1;
 		}
+	} else if (fl->fl_kind == FL_LEASE && !strcmp(fl_type, "BREAKING")) {
+		pr_err("Breaking leases are not supported (%d): %s\n",
+			num, buf);
 	} else {
 		if (!strcmp(fl_option, "UNLCK")) {
 			fl->fl_ltype |= F_UNLCK;