[PATCH -V4 6/6] x86: Add new syscalls for x86_64

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

 



Add sys_name_to_handle and sys_open_by_handle syscall for x86_64
Add necessary compat syscall support

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@xxxxxxxxxxxxxxxxxx>
---
 arch/x86/ia32/ia32entry.S        |    2 +
 arch/x86/include/asm/unistd_64.h |    4 ++
 fs/compat.c                      |   72 ++++++++++++++++++++++++++++++++++++++
 include/linux/compat.h           |   14 +++++++
 4 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 59b4556..45cf8f0 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -842,4 +842,6 @@ ia32_sys_call_table:
 	.quad compat_sys_rt_tgsigqueueinfo	/* 335 */
 	.quad sys_perf_event_open
 	.quad compat_sys_recvmmsg
+	.quad compat_sys_name_to_handle
+	.quad compat_sys_open_by_handle		/* 339 */
 ia32_syscall_end:
diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
index ff4307b..99967d0 100644
--- a/arch/x86/include/asm/unistd_64.h
+++ b/arch/x86/include/asm/unistd_64.h
@@ -663,6 +663,10 @@ __SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)
 __SYSCALL(__NR_perf_event_open, sys_perf_event_open)
 #define __NR_recvmmsg				299
 __SYSCALL(__NR_recvmmsg, sys_recvmmsg)
+#define __NR_name_to_handle			300
+__SYSCALL(__NR_name_to_handle, sys_name_to_handle)
+#define __NR_open_by_handle			301
+__SYSCALL(__NR_open_by_handle, sys_open_by_handle)
 
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
diff --git a/fs/compat.c b/fs/compat.c
index 4b6ed03..5a03a5b 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -2310,3 +2310,75 @@ asmlinkage long compat_sys_timerfd_gettime(int ufd,
 }
 
 #endif /* CONFIG_TIMERFD */
+
+long get_compat_file_handle(struct file_handle *dst,
+			struct compat_file_handle __user *src)
+{
+	compat_uptr_t f_handle;
+
+	if (!access_ok(VERIFY_READ, src, sizeof(*src)) ||
+		__get_user(dst->handle_size, &src->handle_size) ||
+		__get_user(dst->handle_type, &src->handle_type) ||
+		copy_from_user(dst->fsid.uuid,
+			src->fsid.uuid, sizeof(dst->fsid.uuid)) ||
+		__get_user(f_handle, &src->f_handle)) {
+		return -EFAULT;
+	}
+	dst->f_handle = compat_ptr(f_handle);
+	return 0;
+}
+
+long put_compat_file_handle(struct compat_file_handle __user *dst,
+			struct file_handle *src)
+{
+	/*
+	 * dst->f_handle is copied from do_sys_name_to_handle
+	 */
+	return (!access_ok(VERIFY_WRITE, dst, sizeof(*dst)) ||
+		__put_user(src->handle_size, &dst->handle_size) ||
+		__put_user(src->handle_type, &dst->handle_type) ||
+		copy_to_user(dst->fsid.uuid,
+			src->fsid.uuid, sizeof(dst->fsid.uuid))) ? -EFAULT : 0;
+}
+
+
+asmlinkage long compat_sys_name_to_handle(const char __user *name,
+					struct compat_file_handle __user *uh)
+{
+	long ret1, ret2;
+	compat_uptr_t f_handle;
+	struct file_handle handle;
+
+	ret1 = (!access_ok(VERIFY_READ, uh, sizeof(*uh)) ||
+		__get_user(handle.handle_size, &uh->handle_size) ||
+		__get_user(f_handle, &uh->f_handle)) ? -EFAULT : 0;
+	if (ret1)
+		return ret1;
+
+	handle.f_handle = compat_ptr(f_handle);
+	ret1 = do_sys_name_to_handle(name, &handle);
+	if ((ret1 == -EOVERFLOW) || !ret1)
+		ret2 = put_compat_file_handle(uh, &handle) ? -EFAULT : 0;
+
+	if (ret1)
+		return ret1;
+	if (ret2)
+		return ret2;
+	return 0;
+}
+
+asmlinkage long compat_sys_open_by_handle(struct compat_file_handle __user *uh,
+					int flags)
+{
+	long error;
+	struct file_handle handle;
+
+	error = get_compat_file_handle(&handle, uh) ? -EFAULT : 0;
+	if (error)
+		return error;
+
+	/* we don't want to set the O_LARGEFILE flag */
+	error = do_sys_open_by_handle(&handle, flags);
+
+	return error;
+}
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 717c691..6d2fda1 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -12,6 +12,7 @@
 #include <linux/sem.h>
 #include <linux/socket.h>
 #include <linux/if.h>
+#include <linux/fs.h>
 
 #include <asm/compat.h>
 #include <asm/siginfo.h>
@@ -209,6 +210,15 @@ struct compat_robust_list_head {
 	compat_uptr_t			list_op_pending;
 };
 
+struct compat_file_handle {
+	int handle_size;
+	int handle_type;
+	/* File system identifier */
+	struct uuid fsid;
+	/* file identifier */
+	compat_uptr_t f_handle;
+};
+
 extern void compat_exit_robust_list(struct task_struct *curr);
 
 asmlinkage long
@@ -355,6 +365,10 @@ asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user * filename,
 				      int flag);
 asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
 				  int flags, int mode);
+asmlinkage long compat_sys_name_to_handle(const char __user *name,
+					struct compat_file_handle __user *uh);
+asmlinkage long compat_sys_open_by_handle(struct compat_file_handle __user *uh,
+					int flags);
 
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
-- 
1.7.0.4.360.g11766c

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[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