From b9c14a09b032bd896523a2d6e10f5bf87df45b55 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Fri, 24 Apr 2015 14:49:14 +0300 Subject: [PATCH] kerndat: check the lock field in fdinfo (v2) Starting with the 4.1 kernel, fdinfo contains information about file locks. v2: s/has_lock/has_fdinfo_lock/ Signed-off-by: Andrey Vagin Signed-off-by: Pavel Emelyanov --- cr-check.c | 20 ++++++++++++++++++++ include/kerndat.h | 2 ++ kerndat.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/cr-check.c b/cr-check.c index 3518773c2..4baf730e7 100644 --- a/cr-check.c +++ b/cr-check.c @@ -671,6 +671,23 @@ static int check_aio_remap(void) return 0; } +static int check_fdinfo_lock(void) +{ + if (kerndat_fdinfo_has_lock()) + return -1; + + if (!kdat.has_fdinfo_lock) { + if (!opts.check_ms_kernel) { + pr_err("fdinfo doesn't contain the lock field\n"); + return -1; + } else { + pr_warn("fdinfo doesn't contain the lock field\n"); + } + } + + return 0; +} + static int (*chk_feature)(void); int cr_check(void) @@ -723,6 +740,7 @@ int cr_check(void) ret |= check_timerfd(); ret |= check_mnt_id(); ret |= check_aio_remap(); + ret |= check_fdinfo_lock(); out: if (!ret) @@ -774,6 +792,8 @@ int check_add_feature(char *feat) chk_feature = check_tun; else if (!strcmp(feat, "userns")) chk_feature = check_userns; + else if (!strcmp(feat, "fdinfo_lock")) + chk_feature = check_fdinfo_lock; else { pr_err("Unknown feature %s\n", feat); return -1; diff --git a/include/kerndat.h b/include/kerndat.h index 12517d123..c9e902a35 100644 --- a/include/kerndat.h +++ b/include/kerndat.h @@ -13,6 +13,7 @@ struct stat; extern int kerndat_init(void); extern int kerndat_init_rst(void); extern int kerndat_get_dirty_track(void); +extern int kerndat_fdinfo_has_lock(void); struct kerndat_s { dev_t shmem_dev; @@ -21,6 +22,7 @@ struct kerndat_s { u64 zero_page_pfn; bool has_dirty_track; bool has_memfd; + bool has_fdinfo_lock; }; extern struct kerndat_s kdat; diff --git a/kerndat.c b/kerndat.c index 7946ab41f..6745dbb02 100644 --- a/kerndat.c +++ b/kerndat.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -273,6 +274,42 @@ static bool kerndat_has_memfd_create(void) return 0; } +int kerndat_fdinfo_has_lock() +{ + int fd, pfd = -1, exit_code = -1, len; + char buf[PAGE_SIZE]; + + fd = open("/proc/locks", O_RDONLY); + if (fd < 0) { + pr_perror("Unable to open /proc/locks"); + return -1; + } + + if (flock(fd, LOCK_SH)) { + pr_perror("Can't take a lock\n"); + return -1; + } + + pfd = open_proc(PROC_SELF, "fdinfo/%d", fd); + if (pfd < 0) + goto out; + + len = read(pfd, buf, sizeof(buf)); + if (len < 0) { + pr_perror("Unable to read"); + goto out; + } + + kdat.has_fdinfo_lock = (strstr(buf, "lock:") != NULL); + + exit_code = 0; +out: + close(pfd); + close(fd); + + return exit_code; +} + int kerndat_init(void) { int ret; @@ -284,6 +321,8 @@ int kerndat_init(void) ret = init_zero_page_pfn(); if (!ret) ret = get_last_cap(); + if (!ret) + ret = kerndat_fdinfo_has_lock(); return ret; }