diff --git a/criu/file-lock.c b/criu/file-lock.c index 821821f59..834594e4a 100644 --- a/criu/file-lock.c +++ b/criu/file-lock.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #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,16 @@ static int restore_file_lock(FileLockEntry *fle) pr_err("Can not set ofd lock!\n"); goto err; } + } else if (fle->flag & FL_LEASE) { + pr_info("(lease)flag: %d, type: %d, pid: %d, fd: %d, " + "start: %8"PRIx64", len: %8"PRIx64"\n", + fle->flag, fle->type, fle->pid, fle->fd, + fle->start, fle->len); + 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 ffcef9eba..b188106f4 100644 --- a/criu/proc_parse.c +++ b/criu/proc_parse.c @@ -2087,6 +2087,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; @@ -2103,6 +2105,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;