From 2fb18b5d309c7ddcc66bbb317abe758921101a4e Mon Sep 17 00:00:00 2001 From: Alexey Min Date: Mon, 1 Jul 2019 03:29:30 +0300 Subject: [PATCH] samsung-klte: backport memfd_create() syscall (!479) This brings in several patches needed to add support for a memfd_create() syscall into kernel version 3.4 from kernel version 3.17. This is required for running lxc >= 3.1.0-r1 with security patch that fixes CVE-2019-5736. In short, security issue was: in a privileged container root process could overwrite lxc-start executable by opening its file descriptor and rewriting executable contents. This is where memfd comes to help: you can create an in-memory file, copy your executable there, and place a set of SEALS to protect it from modifying at a deep level. Then you fexecve() that fd and you're safe. For example, pulseaudio also can benefit from having memfd_create() implemented. This backports the following commits from upstream linux: - dd37978c50bc8b354e5c4633f69387f16572fdac: cache the value of file_inode() in struct file commit from linux-3.10 to have an f_inode member inside struct file and a helper function file_inode() that is used in some of the following commits - 40e041a2c858b3caefc757e26cb85bfceae5062b shm: add sealing API from 3.17: security measure called SEALS, that you can put on memfd file to restrict operations on it - 9183df25fe7b194563db3fec6dc3202a5855839c shm: add memfd_create() syscall also from 3.17 - 503e6636b6f96056210062be703356f4253b6db9 asm-generic: add memfd_create system call to unistd.h - e57e41931134e09fc6c03c8d4eb19d516cc6e59b ARM: wire up memfd_create syscall The last two are needed to make the syscall visible/usable from userspace, one in generic context, other for ARM arch. The test program (https://github.com/minlexx/test_memfd/) was written to verify that this works. [ci:skip-build]: already built successfully in CI --- ...e-value-of-file_inode-in-struct-file.patch | 101 +++++ .../0010-Backport-shm-add-sealing-API.patch | 367 ++++++++++++++++++ ...ackport-shm-add-memfd_create-syscall.patch | 198 ++++++++++ ...memfd_create-system-call-to-unistd.h.patch | 41 ++ ...ort-ARM-wire-up-memfd_create-syscall.patch | 42 ++ device/linux-samsung-klte/APKBUILD | 19 +- 6 files changed, 764 insertions(+), 4 deletions(-) create mode 100644 device/linux-samsung-klte/0009-Backport-cache-the-value-of-file_inode-in-struct-file.patch create mode 100644 device/linux-samsung-klte/0010-Backport-shm-add-sealing-API.patch create mode 100644 device/linux-samsung-klte/0011-Backport-shm-add-memfd_create-syscall.patch create mode 100644 device/linux-samsung-klte/0012-Backport-asm-generic-add-memfd_create-system-call-to-unistd.h.patch create mode 100644 device/linux-samsung-klte/0013-Backport-ARM-wire-up-memfd_create-syscall.patch diff --git a/device/linux-samsung-klte/0009-Backport-cache-the-value-of-file_inode-in-struct-file.patch b/device/linux-samsung-klte/0009-Backport-cache-the-value-of-file_inode-in-struct-file.patch new file mode 100644 index 000000000..4846985bf --- /dev/null +++ b/device/linux-samsung-klte/0009-Backport-cache-the-value-of-file_inode-in-struct-file.patch @@ -0,0 +1,101 @@ +From 71846fb0e72ac8f7c05ca85f28b50cae4703acfc Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Mon, 1 Jul 2019 23:47:19 +0300 +Subject: [PATCH 1/5] cache the value of file_inode() in struct file + +Note that this thing does *not* contribute to inode refcount; +it's pinned down by dentry. + +Signed-off-by: Al Viro +--- + fs/f2fs/f2fs.h | 3 ++- + fs/file_table.c | 2 ++ + fs/open.c | 2 ++ + include/linux/fs.h | 7 +++++++ + 4 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index 6ef8c890a57..2b511f8a416 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -1844,10 +1844,11 @@ static inline bool f2fs_cp_error(struct f2fs_sb_info *sbi) + return is_set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG); + } + ++/* Implementation of file_inode added to include/linux/fs.h + static inline struct inode *file_inode(struct file *f) + { + return f->f_path.dentry->d_inode; +-} ++}*/ + + static inline bool is_dot_dotdot(const struct qstr *str) + { +diff --git a/fs/file_table.c b/fs/file_table.c +index a01710a6ff3..07838af0737 100644 +--- a/fs/file_table.c ++++ b/fs/file_table.c +@@ -172,6 +172,7 @@ struct file *alloc_file(struct path *path, fmode_t mode, + return NULL; + + file->f_path = *path; ++ file->f_inode = path->dentry->d_inode; + file->f_mapping = path->dentry->d_inode->i_mapping; + file->f_mode = mode; + file->f_op = fop; +@@ -254,6 +255,7 @@ static void __fput(struct file *file) + drop_file_write_access(file); + file->f_path.dentry = NULL; + file->f_path.mnt = NULL; ++ file->f_inode = NULL; + file_free(file); + dput(dentry); + mntput(mnt); +diff --git a/fs/open.c b/fs/open.c +index 3f716e9b896..2388e788e10 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -673,6 +673,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, + f->f_mode = FMODE_PATH; + + inode = dentry->d_inode; ++ f->f_inode = dentry->d_inode; + if (f->f_mode & FMODE_WRITE) { + error = __get_file_write_access(inode, mnt); + if (error) +@@ -748,6 +749,7 @@ cleanup_all: + } + f->f_path.dentry = NULL; + f->f_path.mnt = NULL; ++ f->f_inode = NULL; + cleanup_file: + put_filp(f); + dput(dentry); +diff --git a/include/linux/fs.h b/include/linux/fs.h +index ef6e82ce1c1..11265501da0 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1029,6 +1029,7 @@ struct file { + struct path f_path; + #define f_dentry f_path.dentry + #define f_vfsmnt f_path.mnt ++ struct inode *f_inode; /* cached value */ + const struct file_operations *f_op; + + /* +@@ -2304,6 +2305,12 @@ static inline bool execute_ok(struct inode *inode) + return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode); + } + ++static inline struct inode *file_inode(struct file *f) ++{ ++ /* return f->f_path.dentry->d_inode; / can also use this */ ++ return f->f_inode; ++} ++ + /* + * get_write_access() gets write permission for a file. + * put_write_access() releases this write permission. +-- +2.20.1 + diff --git a/device/linux-samsung-klte/0010-Backport-shm-add-sealing-API.patch b/device/linux-samsung-klte/0010-Backport-shm-add-sealing-API.patch new file mode 100644 index 000000000..9bebb985d --- /dev/null +++ b/device/linux-samsung-klte/0010-Backport-shm-add-sealing-API.patch @@ -0,0 +1,367 @@ +From 893282e935b9b1eb212eaf556843a47069e7d2a6 Mon Sep 17 00:00:00 2001 +From: David Herrmann +Date: Mon, 1 Jul 2019 00:54:54 +0300 +Subject: [PATCH 2/5] shm: add sealing API + +If two processes share a common memory region, they usually want some +guarantees to allow safe access. This often includes: + - one side cannot overwrite data while the other reads it + - one side cannot shrink the buffer while the other accesses it + - one side cannot grow the buffer beyond previously set boundaries + +If there is a trust-relationship between both parties, there is no need +for policy enforcement. However, if there's no trust relationship (eg., +for general-purpose IPC) sharing memory-regions is highly fragile and +often not possible without local copies. Look at the following two +use-cases: + + 1) A graphics client wants to share its rendering-buffer with a + graphics-server. The memory-region is allocated by the client for + read/write access and a second FD is passed to the server. While + scanning out from the memory region, the server has no guarantee that + the client doesn't shrink the buffer at any time, requiring rather + cumbersome SIGBUS handling. + 2) A process wants to perform an RPC on another process. To avoid huge + bandwidth consumption, zero-copy is preferred. After a message is + assembled in-memory and a FD is passed to the remote side, both sides + want to be sure that neither modifies this shared copy, anymore. The + source may have put sensible data into the message without a separate + copy and the target may want to parse the message inline, to avoid a + local copy. + +While SIGBUS handling, POSIX mandatory locking and MAP_DENYWRITE provide +ways to achieve most of this, the first one is unproportionally ugly to +use in libraries and the latter two are broken/racy or even disabled due +to denial of service attacks. + +This patch introduces the concept of SEALING. If you seal a file, a +specific set of operations is blocked on that file forever. Unlike locks, +seals can only be set, never removed. Hence, once you verified a specific +set of seals is set, you're guaranteed that no-one can perform the blocked +operations on this file, anymore. + +An initial set of SEALS is introduced by this patch: + - SHRINK: If SEAL_SHRINK is set, the file in question cannot be reduced + in size. This affects ftruncate() and open(O_TRUNC). + - GROW: If SEAL_GROW is set, the file in question cannot be increased + in size. This affects ftruncate(), fallocate() and write(). + - WRITE: If SEAL_WRITE is set, no write operations (besides resizing) + are possible. This affects fallocate(PUNCH_HOLE), mmap() and + write(). + - SEAL: If SEAL_SEAL is set, no further seals can be added to a file. + This basically prevents the F_ADD_SEAL operation on a file and + can be set to prevent others from adding further seals that you + don't want. + +The described use-cases can easily use these seals to provide safe use +without any trust-relationship: + + 1) The graphics server can verify that a passed file-descriptor has + SEAL_SHRINK set. This allows safe scanout, while the client is + allowed to increase buffer size for window-resizing on-the-fly. + Concurrent writes are explicitly allowed. + 2) For general-purpose IPC, both processes can verify that SEAL_SHRINK, + SEAL_GROW and SEAL_WRITE are set. This guarantees that neither + process can modify the data while the other side parses it. + Furthermore, it guarantees that even with writable FDs passed to the + peer, it cannot increase the size to hit memory-limits of the source + process (in case the file-storage is accounted to the source). + +The new API is an extension to fcntl(), adding two new commands: + F_GET_SEALS: Return a bitset describing the seals on the file. This + can be called on any FD if the underlying file supports + sealing. + F_ADD_SEALS: Change the seals of a given file. This requires WRITE + access to the file and F_SEAL_SEAL may not already be set. + Furthermore, the underlying file must support sealing and + there may not be any existing shared mapping of that file. + Otherwise, EBADF/EPERM is returned. + The given seals are _added_ to the existing set of seals + on the file. You cannot remove seals again. + +The fcntl() handler is currently specific to shmem and disabled on all +files. A file needs to explicitly support sealing for this interface to +work. A separate syscall is added in a follow-up, which creates files that +support sealing. There is no intention to support this on other +file-systems. Semantics are unclear for non-volatile files and we lack any +use-case right now. Therefore, the implementation is specific to shmem. + +Signed-off-by: David Herrmann +Acked-by: Hugh Dickins +Cc: Michael Kerrisk +Cc: Ryan Lortie +Cc: Lennart Poettering +Cc: Daniel Mack +Cc: Andy Lutomirski +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + fs/fcntl.c | 5 ++ + include/linux/fcntl.h | 16 +++++ + include/linux/shmem_fs.h | 18 ++++++ + mm/shmem.c | 122 +++++++++++++++++++++++++++++++++++++++ + 4 files changed, 161 insertions(+) + +diff --git a/fs/fcntl.c b/fs/fcntl.c +index b17b568001e..e660ffc9ac8 100644 +--- a/fs/fcntl.c ++++ b/fs/fcntl.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -431,6 +432,10 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, + case F_GETPIPE_SZ: + err = pipe_fcntl(filp, cmd, arg); + break; ++ case F_ADD_SEALS: ++ case F_GET_SEALS: ++ err = shmem_fcntl(filp, cmd, arg); ++ break; + default: + break; + } +diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h +index f550f894ba1..2c39b178797 100644 +--- a/include/linux/fcntl.h ++++ b/include/linux/fcntl.h +@@ -27,6 +27,22 @@ + #define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7) + #define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8) + ++/* ++ * Set/Get seals ++ */ ++#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) ++#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) ++ ++/* ++ * Types of seals ++ */ ++#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */ ++#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */ ++#define F_SEAL_GROW 0x0004 /* prevent file from growing */ ++#define F_SEAL_WRITE 0x0008 /* prevent writes */ ++/* (1U << 31) is reserved for signed error codes */ ++ ++ + /* + * Types of directory notifications that may be requested. + */ +diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h +index 79ab2555b3b..c08c0907bf5 100644 +--- a/include/linux/shmem_fs.h ++++ b/include/linux/shmem_fs.h +@@ -1,6 +1,7 @@ + #ifndef __SHMEM_FS_H + #define __SHMEM_FS_H + ++#include + #include + #include + #include +@@ -11,6 +12,7 @@ + struct shmem_inode_info { + spinlock_t lock; + unsigned long flags; ++ unsigned int seals; /* shmem seals */ + unsigned long alloced; /* data pages alloced to file */ + union { + unsigned long swapped; /* subtotal assigned to swap */ +@@ -61,4 +63,20 @@ static inline struct page *shmem_read_mapping_page( + mapping_gfp_mask(mapping)); + } + ++#ifdef CONFIG_TMPFS ++ ++extern int shmem_add_seals(struct file *file, unsigned int seals); ++extern int shmem_get_seals(struct file *file); ++extern long shmem_fcntl(struct file *file, unsigned int cmd, unsigned long arg); ++ ++#else ++ ++static inline long shmem_fcntl(struct file *f, unsigned int c, unsigned long a) ++{ ++ return -EINVAL; ++} ++ ++#endif ++ ++ + #endif +diff --git a/mm/shmem.c b/mm/shmem.c +index 788a30082a9..1a232f8d8cb 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -63,6 +63,7 @@ static struct vfsmount *shm_mnt; + #include + #include + #include ++#include + + #include + #include +@@ -560,6 +561,7 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range); + static int shmem_setattr(struct dentry *dentry, struct iattr *attr) + { + struct inode *inode = dentry->d_inode; ++ struct shmem_inode_info *info = SHMEM_I(inode); + int error; + + error = inode_change_ok(inode, attr); +@@ -570,6 +572,11 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr) + loff_t oldsize = inode->i_size; + loff_t newsize = attr->ia_size; + ++ /* protected by i_mutex */ ++ if ((newsize < oldsize && (info->seals & F_SEAL_SHRINK)) || ++ (newsize > oldsize && (info->seals & F_SEAL_GROW))) ++ return -EPERM; ++ + if (newsize != oldsize) { + i_size_write(inode, newsize); + inode->i_ctime = inode->i_mtime = CURRENT_TIME; +@@ -1279,6 +1286,7 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode + info = SHMEM_I(inode); + memset(info, 0, (char *)inode - (char *)info); + spin_lock_init(&info->lock); ++ info->seals = F_SEAL_SEAL; + info->flags = flags & VM_NORESERVE; + INIT_LIST_HEAD(&info->swaplist); + INIT_LIST_HEAD(&info->xattr_list); +@@ -1332,7 +1340,17 @@ shmem_write_begin(struct file *file, struct address_space *mapping, + struct page **pagep, void **fsdata) + { + struct inode *inode = mapping->host; ++ struct shmem_inode_info *info = SHMEM_I(inode); + pgoff_t index = pos >> PAGE_CACHE_SHIFT; ++ ++ /* i_mutex is held by caller */ ++ if (unlikely(info->seals)) { ++ if (info->seals & F_SEAL_WRITE) ++ return -EPERM; ++ if ((info->seals & F_SEAL_GROW) && pos + len > inode->i_size) ++ return -EPERM; ++ } ++ + return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL); + } + +@@ -1605,6 +1623,110 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, + return error; + } + ++static int shmem_wait_for_pins(struct address_space *mapping) ++{ ++ return 0; ++} ++ ++#define F_ALL_SEALS (F_SEAL_SEAL | \ ++ F_SEAL_SHRINK | \ ++ F_SEAL_GROW | \ ++ F_SEAL_WRITE) ++ ++int shmem_add_seals(struct file *file, unsigned int seals) ++{ ++ struct inode *inode = file_inode(file); ++ struct shmem_inode_info *info = SHMEM_I(inode); ++ int error; ++ ++ /* ++ * SEALING ++ * Sealing allows multiple parties to share a shmem-file but restrict ++ * access to a specific subset of file operations. Seals can only be ++ * added, but never removed. This way, mutually untrusted parties can ++ * share common memory regions with a well-defined policy. A malicious ++ * peer can thus never perform unwanted operations on a shared object. ++ * ++ * Seals are only supported on special shmem-files and always affect ++ * the whole underlying inode. Once a seal is set, it may prevent some ++ * kinds of access to the file. Currently, the following seals are ++ * defined: ++ * SEAL_SEAL: Prevent further seals from being set on this file ++ * SEAL_SHRINK: Prevent the file from shrinking ++ * SEAL_GROW: Prevent the file from growing ++ * SEAL_WRITE: Prevent write access to the file ++ * ++ * As we don't require any trust relationship between two parties, we ++ * must prevent seals from being removed. Therefore, sealing a file ++ * only adds a given set of seals to the file, it never touches ++ * existing seals. Furthermore, the "setting seals"-operation can be ++ * sealed itself, which basically prevents any further seal from being ++ * added. ++ * ++ * Semantics of sealing are only defined on volatile files. Only ++ * anonymous shmem files support sealing. More importantly, seals are ++ * never written to disk. Therefore, there's no plan to support it on ++ * other file types. ++ */ ++ ++ if (file->f_op != &shmem_file_operations) ++ return -EINVAL; ++ if (!(file->f_mode & FMODE_WRITE)) ++ return -EPERM; ++ if (seals & ~(unsigned int)F_ALL_SEALS) ++ return -EINVAL; ++ ++ mutex_lock(&inode->i_mutex); ++ ++ if (info->seals & F_SEAL_SEAL) { ++ error = -EPERM; ++ goto unlock; ++ } ++ ++ /* TODO: this is the place to actually apply seals to ++ * file->f_mapping, but this was not backported yet */ ++ ++ info->seals |= seals; ++ error = 0; ++ ++unlock: ++ mutex_unlock(&inode->i_mutex); ++ return error; ++} ++EXPORT_SYMBOL_GPL(shmem_add_seals); ++ ++int shmem_get_seals(struct file *file) ++{ ++ if (file->f_op != &shmem_file_operations) ++ return -EINVAL; ++ ++ return SHMEM_I(file_inode(file))->seals; ++} ++EXPORT_SYMBOL_GPL(shmem_get_seals); ++ ++long shmem_fcntl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ long error; ++ ++ switch (cmd) { ++ case F_ADD_SEALS: ++ /* disallow upper 32bit */ ++ if (arg > UINT_MAX) ++ return -EINVAL; ++ ++ error = shmem_add_seals(file, arg); ++ break; ++ case F_GET_SEALS: ++ error = shmem_get_seals(file); ++ break; ++ default: ++ error = -EINVAL; ++ break; ++ } ++ ++ return error; ++} ++ + static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf) + { + struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb); +-- +2.20.1 + diff --git a/device/linux-samsung-klte/0011-Backport-shm-add-memfd_create-syscall.patch b/device/linux-samsung-klte/0011-Backport-shm-add-memfd_create-syscall.patch new file mode 100644 index 000000000..b89d5d864 --- /dev/null +++ b/device/linux-samsung-klte/0011-Backport-shm-add-memfd_create-syscall.patch @@ -0,0 +1,198 @@ +From 01fc0d7a8df67bd3a1f2cf7ffd5f74c6fadd7c85 Mon Sep 17 00:00:00 2001 +From: David Herrmann +Date: Tue, 2 Jul 2019 02:36:29 +0300 +Subject: [PATCH 3/5] shm: add memfd_create() syscall + +memfd_create() is similar to mmap(MAP_ANON), but returns a file-descriptor +that you can pass to mmap(). It can support sealing and avoids any +connection to user-visible mount-points. Thus, it's not subject to quotas +on mounted file-systems, but can be used like malloc()'ed memory, but with +a file-descriptor to it. + +memfd_create() returns the raw shmem file, so calls like ftruncate() can +be used to modify the underlying inode. Also calls like fstat() will +return proper information and mark the file as regular file. If you want +sealing, you can specify MFD_ALLOW_SEALING. Otherwise, sealing is not +supported (like on all other regular files). + +Compared to O_TMPFILE, it does not require a tmpfs mount-point and is not +subject to a filesystem size limit. It is still properly accounted to +memcg limits, though, and to the same overcommit or no-overcommit +accounting as all user memory. + +Signed-off-by: David Herrmann +Acked-by: Hugh Dickins +Cc: Michael Kerrisk +Cc: Ryan Lortie +Cc: Lennart Poettering +Cc: Daniel Mack +Cc: Andy Lutomirski +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + arch/x86/syscalls/syscall_32.tbl | 2 + + arch/x86/syscalls/syscall_64.tbl | 2 + + include/linux/syscalls.h | 1 + + include/uapi/linux/memfd.h | 8 ++++ + kernel/sys_ni.c | 1 + + mm/shmem.c | 74 ++++++++++++++++++++++++++++++++ + 6 files changed, 88 insertions(+) + create mode 100644 include/uapi/linux/memfd.h + +diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl +index 64e55260fbc..498d12b9af8 100644 +--- a/arch/x86/syscalls/syscall_32.tbl ++++ b/arch/x86/syscalls/syscall_32.tbl +@@ -356,3 +356,5 @@ + 347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv + 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev + 354 i386 seccomp sys_seccomp ++# 355 i386 getrandom sys_getrandom ++356 i386 memfd_create sys_memfd_create +diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl +index 33335d11d7b..4887a0fa042 100644 +--- a/arch/x86/syscalls/syscall_64.tbl ++++ b/arch/x86/syscalls/syscall_64.tbl +@@ -319,6 +319,8 @@ + 310 64 process_vm_readv sys_process_vm_readv + 311 64 process_vm_writev sys_process_vm_writev + 317 common seccomp sys_seccomp ++# 318 common getrandom sys_getrandom ++319 common memfd_create sys_memfd_create + + # + # x32-specific system call numbers start at 512 to avoid cache impact +diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h +index da352d5a271..c1cc0e12cf4 100644 +--- a/include/linux/syscalls.h ++++ b/include/linux/syscalls.h +@@ -813,6 +813,7 @@ asmlinkage long sys_timerfd_settime(int ufd, int flags, + asmlinkage long sys_timerfd_gettime(int ufd, struct itimerspec __user *otmr); + asmlinkage long sys_eventfd(unsigned int count); + asmlinkage long sys_eventfd2(unsigned int count, int flags); ++asmlinkage long sys_memfd_create(const char __user *uname_ptr, unsigned int flags); + asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len); + asmlinkage long sys_old_readdir(unsigned int, struct old_linux_dirent __user *, unsigned int); + asmlinkage long sys_pselect6(int, fd_set __user *, fd_set __user *, +diff --git a/include/uapi/linux/memfd.h b/include/uapi/linux/memfd.h +new file mode 100644 +index 00000000000..9a772654307 +--- /dev/null ++++ b/include/uapi/linux/memfd.h +@@ -0,0 +1,8 @@ ++#ifndef _UAPI_LINUX_MEMFD_H ++#define _UAPI_LINUX_MEMFD_H ++ ++/* flags for memfd_create(2) (unsigned int) */ ++#define MFD_CLOEXEC 0x0001U ++#define MFD_ALLOW_SEALING 0x0002U ++ ++#endif /* _UAPI_LINUX_MEMFD_H */ +diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c +index 026f30a8985..b97ab3a6dc9 100644 +--- a/kernel/sys_ni.c ++++ b/kernel/sys_ni.c +@@ -191,6 +191,7 @@ cond_syscall(compat_sys_timerfd_settime); + cond_syscall(compat_sys_timerfd_gettime); + cond_syscall(sys_eventfd); + cond_syscall(sys_eventfd2); ++cond_syscall(sys_memfd_create); + + /* performance counters: */ + cond_syscall(sys_perf_event_open); +diff --git a/mm/shmem.c b/mm/shmem.c +index 1a232f8d8cb..3b9580b0808 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -63,7 +63,9 @@ static struct vfsmount *shm_mnt; + #include + #include + #include ++#include + #include ++#include + + #include + #include +@@ -2492,6 +2494,78 @@ static int shmem_show_options(struct seq_file *seq, struct dentry *root) + shmem_show_mpol(seq, sbinfo->mpol); + return 0; + } ++ ++ ++#define MFD_NAME_PREFIX "memfd:" ++#define MFD_NAME_PREFIX_LEN (sizeof(MFD_NAME_PREFIX) - 1) ++#define MFD_NAME_MAX_LEN (NAME_MAX - MFD_NAME_PREFIX_LEN) ++ ++#define MFD_ALL_FLAGS (MFD_CLOEXEC | MFD_ALLOW_SEALING) ++ ++SYSCALL_DEFINE2(memfd_create, ++ const char __user *, uname, ++ unsigned int, flags) ++{ ++ struct shmem_inode_info *info; ++ struct file *file; ++ int fd, error; ++ char *name; ++ long len; ++ ++ if (flags & ~(unsigned int)MFD_ALL_FLAGS) ++ return -EINVAL; ++ ++ /* length includes terminating zero */ ++ len = strnlen_user(uname, MFD_NAME_MAX_LEN + 1); ++ if (len <= 0) ++ return -EFAULT; ++ if (len > MFD_NAME_MAX_LEN + 1) ++ return -EINVAL; ++ ++ name = kmalloc(len + MFD_NAME_PREFIX_LEN, GFP_TEMPORARY); ++ if (!name) ++ return -ENOMEM; ++ ++ strcpy(name, MFD_NAME_PREFIX); ++ if (copy_from_user(&name[MFD_NAME_PREFIX_LEN], uname, len)) { ++ error = -EFAULT; ++ goto err_name; ++ } ++ ++ /* terminating-zero may have changed after strnlen_user() returned */ ++ if (name[len + MFD_NAME_PREFIX_LEN - 1]) { ++ error = -EFAULT; ++ goto err_name; ++ } ++ ++ fd = get_unused_fd_flags((flags & MFD_CLOEXEC) ? O_CLOEXEC : 0); ++ if (fd < 0) { ++ error = fd; ++ goto err_name; ++ } ++ ++ file = shmem_file_setup(name, 0, VM_NORESERVE); ++ if (IS_ERR(file)) { ++ error = PTR_ERR(file); ++ goto err_fd; ++ } ++ info = SHMEM_I(file_inode(file)); ++ file->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; ++ file->f_flags |= O_RDWR | O_LARGEFILE; ++ if (flags & MFD_ALLOW_SEALING) ++ info->seals &= ~F_SEAL_SEAL; ++ ++ fd_install(fd, file); ++ kfree(name); ++ return fd; ++ ++err_fd: ++ put_unused_fd(fd); ++err_name: ++ kfree(name); ++ return error; ++} ++ + #endif /* CONFIG_TMPFS */ + + static void shmem_put_super(struct super_block *sb) +-- +2.20.1 + diff --git a/device/linux-samsung-klte/0012-Backport-asm-generic-add-memfd_create-system-call-to-unistd.h.patch b/device/linux-samsung-klte/0012-Backport-asm-generic-add-memfd_create-system-call-to-unistd.h.patch new file mode 100644 index 000000000..888717bee --- /dev/null +++ b/device/linux-samsung-klte/0012-Backport-asm-generic-add-memfd_create-system-call-to-unistd.h.patch @@ -0,0 +1,41 @@ +From b307cbc85399f0aeee3747e1ace50ca036f77c96 Mon Sep 17 00:00:00 2001 +From: Will Deacon +Date: Tue, 2 Jul 2019 02:47:26 +0300 +Subject: [PATCH 4/5] asm-generic: add memfd_create system call to unistd.h + +Commit 9183df25fe7b ("shm: add memfd_create() syscall") added a new +system call (memfd_create) but didn't update the asm-generic unistd +header. + +This patch adds the new system call to the asm-generic version of +unistd.h so that it can be used by architectures such as arm64. + +Cc: Arnd Bergmann +Reviewed-by: David Herrmann +Signed-off-by: Will Deacon +--- + include/asm-generic/unistd.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h +index ae8513b32af..a4fafc379f5 100644 +--- a/include/asm-generic/unistd.h ++++ b/include/asm-generic/unistd.h +@@ -693,9 +693,13 @@ __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \ + compat_sys_process_vm_writev) + #define __NR_seccomp 277 + __SYSCALL(__NR_seccomp, sys_seccomp) ++/*#define __NR_getrandom 278 ++__SYSCALL(__NR_getrandom, sys_getrandom) unfortunately getrandom is not backported yet */ ++#define __NR_memfd_create 279 ++__SYSCALL(__NR_memfd_create, sys_memfd_create) + + #undef __NR_syscalls +-#define __NR_syscalls 278 ++#define __NR_syscalls 280 + + /* + * All syscalls below here should go away really, +-- +2.20.1 + diff --git a/device/linux-samsung-klte/0013-Backport-ARM-wire-up-memfd_create-syscall.patch b/device/linux-samsung-klte/0013-Backport-ARM-wire-up-memfd_create-syscall.patch new file mode 100644 index 000000000..7ba5b45db --- /dev/null +++ b/device/linux-samsung-klte/0013-Backport-ARM-wire-up-memfd_create-syscall.patch @@ -0,0 +1,42 @@ +From c4dd412e68ccbe2e759d6517e902a6f3e7d8f700 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Tue, 2 Jul 2019 02:57:25 +0300 +Subject: [PATCH 5/5] ARM: wire up memfd_create syscall + +Add the memfd_create syscall to ARM. + +Signed-off-by: Russell King +--- + arch/arm/include/asm/unistd.h | 2 ++ + arch/arm/kernel/calls.S | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h +index 6ef9635a174..9b81e87e683 100644 +--- a/arch/arm/include/asm/unistd.h ++++ b/arch/arm/include/asm/unistd.h +@@ -405,6 +405,8 @@ + #define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) + #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) + #define __NR_seccomp (__NR_SYSCALL_BASE+383) ++/*#define __NR_getrandom (__NR_SYSCALL_BASE+384) not ported yet */ ++#define __NR_memfd_create (__NR_SYSCALL_BASE+385) + + /* + * The following SWIs are ARM private. +diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S +index d01eb013b0a..957e262aa86 100644 +--- a/arch/arm/kernel/calls.S ++++ b/arch/arm/kernel/calls.S +@@ -393,6 +393,8 @@ + CALL(sys_ni_syscall) + CALL(sys_ni_syscall) + CALL(sys_seccomp) ++ CALL(sys_ni_syscall) /* no sys_getrandom yet */ ++/* 385 */ CALL(sys_memfd_create) + #ifndef syscalls_counted + .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls + #define syscalls_counted +-- +2.20.1 + diff --git a/device/linux-samsung-klte/APKBUILD b/device/linux-samsung-klte/APKBUILD index a953c9b5c..32ec7683d 100644 --- a/device/linux-samsung-klte/APKBUILD +++ b/device/linux-samsung-klte/APKBUILD @@ -5,7 +5,7 @@ pkgname="linux-samsung-klte" pkgver=3.4.113 -pkgrel=4 +pkgrel=5 pkgdesc="Samsung Galaxy S5 kernel fork" arch="armv7" _carch="arm" @@ -24,7 +24,7 @@ fi # Source _repository="android_kernel_samsung_msm8974" -_commit="b6614591549c558e0712f964c390cb25cf7be20f" +_commit="edfd9dd9be89d15c34f653363a9a3c9108146ca0" _config="config-${_flavor}.${arch}" source=" $pkgname-$_commit.tar.gz::https://github.com/LineageOS/${_repository}/archive/${_commit}.tar.gz @@ -37,7 +37,13 @@ source=" 0006-Fix-xt_connbytes-compile-warning.patch 0007-usb_gadget-set-random-rndis-host-MAC-address-to-prev.patch 0008-Backport-vfs-make-O_PATH-file-descriptors-usable-for.patch + 0009-Backport-cache-the-value-of-file_inode-in-struct-file.patch + 0010-Backport-shm-add-sealing-API.patch + 0011-Backport-shm-add-memfd_create-syscall.patch + 0012-Backport-asm-generic-add-memfd_create-system-call-to-unistd.h.patch + 0013-Backport-ARM-wire-up-memfd_create-syscall.patch " + builddir="$srcdir/${_repository}-${_commit}" prepare() { @@ -84,7 +90,7 @@ package() { INSTALL_MOD_PATH="$pkgdir" modules_install } -sha512sums="3947d670fb3bf9cc3f47be2b13eca0fc2317ad5ab23ba4236cea2642e3e599f638a5f667cbe723d912d14777754ca52b50acb3c1fac932ea90bca2d630de4e67 linux-samsung-klte-b6614591549c558e0712f964c390cb25cf7be20f.tar.gz +sha512sums="d0ccc0cde26e6cad7e2b4cffa9d92b4cd7d11e159738935d87cc044a07679e7aed891379fb0e096b12cd1ba7e1855dd72c94ec6da96ff8e936479c59b4d4eb6c linux-samsung-klte-edfd9dd9be89d15c34f653363a9a3c9108146ca0.tar.gz 2e660d0ac4ffdd5f1a63660a8b61cf83e94122f15126b134a27f58b84fc5424ce4935ef43ca5bff1ec956047b77f7fb7f67e5c1ec976c67712444b370ae6373e config-samsung-klte.armv7 3b4913415bcfe0ff222969f993890c656c7e12b6ee06532bded485d5201c9855b2c87996c5b63423702b89b6b0ca214b5aceeb402571d9c5af084093c157ccb4 0001_fix_return_address.patch 0fc4b1782dfd3bd94fa9ae8ab74b19713f25e9f4a48dcf830072634f247aa3dd8847f001a3e87e9728e057657efd4ae751510e7c408d9b960c907665ca64e61f 0002_gpu-msm-fix-gcc5-compile.patch @@ -93,4 +99,9 @@ a48336bbfead6ad0c84d2fce0c40a3f5530aebdff356a6835cceaf59a50a6f860d2f8027703a9292 e3a9b75de461313ee6ba0e547d7fb97d77a749a11416c44b28110673d3a6f7b01305e74f67c06c8cfea97bde5d3d0cd98a457a03a63560125f5bb84f82f116e1 0005-mdss_fb-Always-allow-to-allocate-map-framebuffer-mem.patch 6bdb3acd4a2d10d59ea16a2147735b94f17070aecebfe55fff724c03335bf1a02cc7539c9fe0a59cb944b6835135fe64956617c8b29847397b2f4df68b602063 0006-Fix-xt_connbytes-compile-warning.patch 27f890cf82027649ba742b606a87ce6a82f9685b075bb7b50bffec77221e70434ee78d118d39048350537c5ecdad208658967e492eeeb997e7f6884fa78ac696 0007-usb_gadget-set-random-rndis-host-MAC-address-to-prev.patch -a2bd1b925ba0e1ba0a68dcb134604abbaddf456426a468662d77bc02f0d09d4d07c0c89001c0973e690e1f7eb9c1cfdd37c2d99ed4cc62f3398582d6b51a7013 0008-Backport-vfs-make-O_PATH-file-descriptors-usable-for.patch" +a2bd1b925ba0e1ba0a68dcb134604abbaddf456426a468662d77bc02f0d09d4d07c0c89001c0973e690e1f7eb9c1cfdd37c2d99ed4cc62f3398582d6b51a7013 0008-Backport-vfs-make-O_PATH-file-descriptors-usable-for.patch +47894281412f1c9d4266812f089c3f2434c1636d74245f392d4b0b7532096f8f5bd698715d9e10c7be6c70892af45de2d2c657bd276332442890b94e1159f8f8 0009-Backport-cache-the-value-of-file_inode-in-struct-file.patch +54d71b32b456a3d0abd090c820214240688484f4cadbbde0304bf3cb5246b1aa3893dd85736dc5db2f3d6f9de1f5e84a1adcf5a661a62586452f1002360dc691 0010-Backport-shm-add-sealing-API.patch +c62d67a5fb28082e86a585b4c64891525db640ce694445f0fb19e67fb8dcd9ccbfbcb6fba8692964fac8b026c39cfa558cf316a7e22828ac13f58f5b9938ef09 0011-Backport-shm-add-memfd_create-syscall.patch +cbf6e4bdf53b02f897923d0f6eea5320acc6760c3f3ed762e69928ced7e3b6f2a5355df4a2fccf560f010a4a1968e7ae1a3f62c2db299857d6bcc9715d932822 0012-Backport-asm-generic-add-memfd_create-system-call-to-unistd.h.patch +2f256f6ec9fa7b240dd1f9417622bfd5a8ca4a9ea12cd2ef171540e1425d4171122c0597fe12af913ef60979ef9a3dce8a6c1c523c91020cb9481560901cc92b 0013-Backport-ARM-wire-up-memfd_create-syscall.patch"