[RFC v3 1/3] VFS adding destroy_creds call

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Filesystems (like NFS) would benefit from an ability to destroy
credentials for the current uid.

Systemcall takes in a file descriptor that's a mount point of the
file system. If a non-directory file descriptor supplied it will
failed with EINVAL. If a bad fd leads to EBADF. And if the file
system doesn't implement destroy_creds, ENOSYS is returned.

Signed-off-by: Olga Kornievskaia <kolga@xxxxxxxxxx>
---
 arch/x86/entry/syscalls/syscall_32.tbl |  1 +
 arch/x86/entry/syscalls/syscall_64.tbl |  1 +
 fs/read_write.c                        | 22 ++++++++++++++++++++++
 include/linux/fs.h                     |  2 ++
 include/linux/syscalls.h               |  2 +-
 include/uapi/asm-generic/unistd.h      |  4 +++-
 kernel/sys_ni.c                        |  1 +
 7 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index 448ac21..298e72b 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -391,3 +391,4 @@
 382	i386	pkey_free		sys_pkey_free
 383	i386	statx			sys_statx
 384	i386	arch_prctl		sys_arch_prctl			compat_sys_arch_prctl
+385	i386	destroy_creds		sys_destroy_creds
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index 5aef183..c8a7e38 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -339,6 +339,7 @@
 330	common	pkey_alloc		sys_pkey_alloc
 331	common	pkey_free		sys_pkey_free
 332	common	statx			sys_statx
+333	common	destroy_creds		sys_destroy_creds
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/fs/read_write.c b/fs/read_write.c
index 0cc7033..f2e169b 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -2041,3 +2041,25 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
 	return ret;
 }
 EXPORT_SYMBOL(vfs_dedupe_file_range);
+
+long vfs_destroy_creds(struct file *fd)
+{
+	struct inode *inode = file_inode(fd);
+
+	if (!S_ISDIR(inode->i_mode))
+		return -EINVAL;
+	if (fd->f_op->destroy_creds)
+		return fd->f_op->destroy_creds(fd);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL(vfs_destroy_creds);
+
+SYSCALL_DEFINE1(destroy_creds, int, fd_in)
+{
+	struct fd f_in;
+
+	f_in = fdget(fd_in);
+	if (!f_in.file)
+		return -EBADF;
+	return vfs_destroy_creds(f_in.file);
+}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6e1fd5d..882bd40 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1699,6 +1699,7 @@ struct file_operations {
 			u64);
 	ssize_t (*dedupe_file_range)(struct file *, u64, u64, struct file *,
 			u64);
+	int (*destroy_creds)(struct file *);
 } __randomize_layout;
 
 struct inode_operations {
@@ -1773,6 +1774,7 @@ extern int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
 					 loff_t len, bool *is_same);
 extern int vfs_dedupe_file_range(struct file *file,
 				 struct file_dedupe_range *same);
+extern long vfs_destroy_creds(struct file *fd);
 
 struct super_operations {
    	struct inode *(*alloc_inode)(struct super_block *sb);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 3cb15ea..3b7b749 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -905,5 +905,5 @@ asmlinkage long sys_pkey_mprotect(unsigned long start, size_t len,
 asmlinkage long sys_pkey_free(int pkey);
 asmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags,
 			  unsigned mask, struct statx __user *buffer);
-
+asmlinkage long sys_destroy_creds(int fd_in);
 #endif
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 061185a..0ad6a0d 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -731,9 +731,11 @@
 __SYSCALL(__NR_pkey_free,     sys_pkey_free)
 #define __NR_statx 291
 __SYSCALL(__NR_statx,     sys_statx)
+#define __NR_destroy_creds 292
+__SYSCALL(__NR_destroy_creds, sys_destroy_creds)
 
 #undef __NR_syscalls
-#define __NR_syscalls 292
+#define __NR_syscalls 293
 
 /*
  * All syscalls below here should go away really,
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 8acef85..cb9ee0b 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -178,6 +178,7 @@ asmlinkage long sys_ni_syscall(void)
 cond_syscall(sys_capget);
 cond_syscall(sys_capset);
 cond_syscall(sys_copy_file_range);
+cond_syscall(sys_destroy_creds);
 
 /* arch-specific weak syscall entries */
 cond_syscall(sys_pciconfig_read);
-- 
1.8.3.1




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux