From 38638705f23d2dbcbb74d5b7da56ce2bb0705eaa Mon Sep 17 00:00:00 2001 From: Quallenauge Date: Tue, 4 Sep 2018 01:55:01 -0100 Subject: [PATCH 1/8] defconfig: Enable RFKILL_INPUT Mitigate BT and WiFi multiexistence in P Change-Id: Ia05a60754bc3e5e22ab44b625a61df9abc3b60db --- arch/arm64/configs/lineage_s2_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/lineage_s2_defconfig b/arch/arm64/configs/lineage_s2_defconfig index f3b2ac10bf74..8829db99767a 100755 --- a/arch/arm64/configs/lineage_s2_defconfig +++ b/arch/arm64/configs/lineage_s2_defconfig @@ -924,7 +924,7 @@ CONFIG_CFG80211_INTERNAL_REGDB=y CONFIG_RFKILL=y CONFIG_RFKILL_PM=y CONFIG_RFKILL_LEDS=y -# CONFIG_RFKILL_INPUT is not set +CONFIG_RFKILL_INPUT=y # CONFIG_RFKILL_REGULATOR is not set # CONFIG_RFKILL_GPIO is not set # CONFIG_NET_9P is not set From b6cf149f60ad885ac67635d8c93c053a9750ef1e Mon Sep 17 00:00:00 2001 From: Subash Abhinov Kasiviswanathan Date: Thu, 23 Feb 2017 18:24:42 -0700 Subject: [PATCH 2/8] net: rmnet_data: Add support to configure custom device name rmnet_data assigns device name by the order they are created. This causes problems which multiple processes are trying to create devices and leads to random device names. Assign device name as specified by user. [mikeioannina]: Backport to 3.10 Change-Id: Ida836c9fd6ac9451e437665838197d90cb9cc53b CRs-Fixed: 2018785 Signed-off-by: Subash Abhinov Kasiviswanathan --- include/uapi/linux/rmnet_data.h | 15 +++++++++++++-- net/rmnet_data/rmnet_data_config.c | 30 +++++++++++++++++++++++++++--- net/rmnet_data/rmnet_data_config.h | 1 + net/rmnet_data/rmnet_data_vnd.c | 11 +++++++---- net/rmnet_data/rmnet_data_vnd.h | 4 ++-- 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/include/uapi/linux/rmnet_data.h b/include/uapi/linux/rmnet_data.h index 8cfe0270ef4f..7ddfa20cec32 100644 --- a/include/uapi/linux/rmnet_data.h +++ b/include/uapi/linux/rmnet_data.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -223,8 +223,19 @@ enum rmnet_netlink_message_types_e { * uint32_t MAP Flow Handle * Returns: status code */ - RMNET_NETLINK_DEL_VND_TC_FLOW + RMNET_NETLINK_DEL_VND_TC_FLOW, + + /* + * RMNET_NETLINK_NEW_VND_WITH_NAME - Creates a new virtual network + * device node with the specified + * device name + * Args: int32_t node number + * char[] vnd_name - Use as name + * Returns: status code + */ + RMNET_NETLINK_NEW_VND_WITH_NAME }; +#define RMNET_NETLINK_NEW_VND_WITH_NAME RMNET_NETLINK_NEW_VND_WITH_NAME enum rmnet_config_endpoint_modes_e { /* Pass the frame up the stack with no modifications to skb->dev */ diff --git a/net/rmnet_data/rmnet_data_config.c b/net/rmnet_data/rmnet_data_config.c index 04d639895381..45a25cd1f6d7 100644 --- a/net/rmnet_data/rmnet_data_config.c +++ b/net/rmnet_data/rmnet_data_config.c @@ -629,6 +629,13 @@ void rmnet_config_netlink_msg_handler(struct sk_buff *skb) rmnet_header->vnd.vnd_name); break; + case RMNET_NETLINK_NEW_VND_WITH_NAME: + resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE; + resp_rmnet->return_code = rmnet_create_vnd_name( + rmnet_header->vnd.id, + rmnet_header->vnd.vnd_name); + break; + case RMNET_NETLINK_FREE_VND: resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE; /* Please check rmnet_vnd_free_dev documentation regarding @@ -1071,11 +1078,11 @@ int rmnet_create_vnd(int id) struct net_device *dev; ASSERT_RTNL(); LOGL("(%d);", id); - return rmnet_vnd_create_dev(id, &dev, NULL); + return rmnet_vnd_create_dev(id, &dev, NULL, 0); } /** - * rmnet_create_vnd() - Create virtual network device node + * rmnet_create_vnd_prefix() - Create virtual network device node * @id: RmNet virtual device node id * @prefix: String prefix for device name * @@ -1087,7 +1094,24 @@ int rmnet_create_vnd_prefix(int id, const char *prefix) struct net_device *dev; ASSERT_RTNL(); LOGL("(%d, \"%s\");", id, prefix); - return rmnet_vnd_create_dev(id, &dev, prefix); + return rmnet_vnd_create_dev(id, &dev, prefix, 0); +} + +/** + * rmnet_create_vnd_name() - Create virtual network device node + * @id: RmNet virtual device node id + * @prefix: String prefix for device name + * + * Return: + * - result of rmnet_vnd_create_dev() + */ +int rmnet_create_vnd_name(int id, const char *name) +{ + struct net_device *dev; + + ASSERT_RTNL(); + LOGL("(%d, \"%s\");", id, name); + return rmnet_vnd_create_dev(id, &dev, name, 1); } /** diff --git a/net/rmnet_data/rmnet_data_config.h b/net/rmnet_data/rmnet_data_config.h index fe668a86eb45..d944ef4f4337 100644 --- a/net/rmnet_data/rmnet_data_config.h +++ b/net/rmnet_data/rmnet_data_config.h @@ -120,6 +120,7 @@ int rmnet_config_notify_cb(struct notifier_block *nb, unsigned long event, void *data); int rmnet_create_vnd(int id); int rmnet_create_vnd_prefix(int id, const char *name); +int rmnet_create_vnd_name(int id, const char *name); int rmnet_free_vnd(int id); #endif /* _RMNET_DATA_CONFIG_H_ */ diff --git a/net/rmnet_data/rmnet_data_vnd.c b/net/rmnet_data/rmnet_data_vnd.c index 50aaf17d6c4c..dd735c04ab1d 100644 --- a/net/rmnet_data/rmnet_data_vnd.c +++ b/net/rmnet_data/rmnet_data_vnd.c @@ -553,7 +553,7 @@ int rmnet_vnd_init(void) * - RMNET_CONFIG_UNKNOWN_ERROR if register_netdevice() fails */ int rmnet_vnd_create_dev(int id, struct net_device **new_device, - const char *prefix) + const char *prefix, int use_name) { struct net_device *dev; char dev_prefix[IFNAMSIZ]; @@ -569,12 +569,15 @@ int rmnet_vnd_create_dev(int id, struct net_device **new_device, return RMNET_CONFIG_DEVICE_IN_USE; } - if (!prefix) + if (!prefix && !use_name) p = scnprintf(dev_prefix, IFNAMSIZ, "%s%%d", RMNET_DATA_DEV_NAME_STR); + else if (prefix && use_name) + p = scnprintf(dev_prefix, IFNAMSIZ, "%s", prefix); + else if (prefix && !use_name) + p = scnprintf(dev_prefix, IFNAMSIZ, "%s%%d", prefix); else - p = scnprintf(dev_prefix, IFNAMSIZ, "%s%%d", - prefix); + return RMNET_CONFIG_BAD_ARGUMENTS; if (p >= (IFNAMSIZ-1)) { LOGE("Specified prefix longer than IFNAMSIZ"); return RMNET_CONFIG_BAD_ARGUMENTS; diff --git a/net/rmnet_data/rmnet_data_vnd.h b/net/rmnet_data/rmnet_data_vnd.h index cb57f571be13..7a1af24fa051 100644 --- a/net/rmnet_data/rmnet_data_vnd.h +++ b/net/rmnet_data/rmnet_data_vnd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,7 +27,7 @@ int rmnet_vnd_do_flow_control(struct net_device *dev, struct rmnet_logical_ep_conf_s *rmnet_vnd_get_le_config(struct net_device *dev); int rmnet_vnd_get_name(int id, char *name, int name_len); int rmnet_vnd_create_dev(int id, struct net_device **new_device, - const char *prefix); + const char *prefix, int use_name); int rmnet_vnd_free_dev(int id); int rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev); int rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev); From 06f77a1183c8b3eccbfc6d934c80f93b1e64fd41 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 7 Jun 2013 01:20:27 -0400 Subject: [PATCH 3/8] [O_TMPFILE] it's still short a few helpers, but infrastructure should be OK now... Change-Id: I0adb8fe9c5029bad3ac52629003c3b78e9442936 Signed-off-by: Al Viro --- arch/alpha/include/uapi/asm/fcntl.h | 1 + arch/parisc/include/uapi/asm/fcntl.h | 1 + arch/sparc/include/uapi/asm/fcntl.h | 1 + fs/dcache.c | 16 ++++++++ fs/ext2/namei.c | 24 +++++++++++ fs/minix/namei.c | 13 ++++++ fs/namei.c | 60 ++++++++++++++++++++++++++++ fs/open.c | 14 ++++--- include/linux/dcache.h | 2 + include/linux/fs.h | 1 + include/uapi/asm-generic/fcntl.h | 4 ++ mm/shmem.c | 32 +++++++++++++++ 12 files changed, 164 insertions(+), 5 deletions(-) diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h index 6d9e805f18a7..dfdadb0b4bef 100644 --- a/arch/alpha/include/uapi/asm/fcntl.h +++ b/arch/alpha/include/uapi/asm/fcntl.h @@ -32,6 +32,7 @@ #define O_SYNC (__O_SYNC|O_DSYNC) #define O_PATH 040000000 +#define O_TMPFILE 0100000000 #define F_GETLK 7 #define F_SETLK 8 diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h index 0304b92ccfea..cc61c475f277 100644 --- a/arch/parisc/include/uapi/asm/fcntl.h +++ b/arch/parisc/include/uapi/asm/fcntl.h @@ -20,6 +20,7 @@ #define O_INVISIBLE 004000000 /* invisible I/O, for DMAPI/XDSM */ #define O_PATH 020000000 +#define O_TMPFILE 040000000 #define F_GETLK64 8 #define F_SETLK64 9 diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h index d0b83f66f356..d73e5e008b0d 100644 --- a/arch/sparc/include/uapi/asm/fcntl.h +++ b/arch/sparc/include/uapi/asm/fcntl.h @@ -35,6 +35,7 @@ #define O_SYNC (__O_SYNC|O_DSYNC) #define O_PATH 0x1000000 +#define O_TMPFILE 0x2000000 #define F_GETOWN 5 /* for sockets. */ #define F_SETOWN 6 /* for sockets. */ diff --git a/fs/dcache.c b/fs/dcache.c index f365091379cd..4003e7d20423 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -3094,6 +3094,22 @@ void d_genocide(struct dentry *root) goto again; } +void d_tmpfile(struct dentry *dentry, struct inode *inode) +{ + inode_dec_link_count(inode); + BUG_ON(dentry->d_name.name != dentry->d_iname || + !hlist_unhashed(&dentry->d_u.d_alias) || + !d_unlinked(dentry)); + spin_lock(&dentry->d_parent->d_lock); + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); + dentry->d_name.len = sprintf(dentry->d_iname, "#%llu", + (unsigned long long)inode->i_ino); + spin_unlock(&dentry->d_lock); + spin_unlock(&dentry->d_parent->d_lock); + d_instantiate(dentry, inode); +} +EXPORT_SYMBOL(d_tmpfile); + /** * find_inode_number - check for dentry with name * @dir: directory to check diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 73b0d9519836..256dd5f4c1c4 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -119,6 +119,29 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode return ext2_add_nondir(dentry, inode); } +static int ext2_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + struct inode *inode = ext2_new_inode(dir, mode, NULL); + if (IS_ERR(inode)) + return PTR_ERR(inode); + + inode->i_op = &ext2_file_inode_operations; + if (ext2_use_xip(inode->i_sb)) { + inode->i_mapping->a_ops = &ext2_aops_xip; + inode->i_fop = &ext2_xip_file_operations; + } else if (test_opt(inode->i_sb, NOBH)) { + inode->i_mapping->a_ops = &ext2_nobh_aops; + inode->i_fop = &ext2_file_operations; + } else { + inode->i_mapping->a_ops = &ext2_aops; + inode->i_fop = &ext2_file_operations; + } + mark_inode_dirty(inode); + d_tmpfile(dentry, inode); + unlock_new_inode(inode); + return 0; +} + static int ext2_mknod (struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev) { struct inode * inode; @@ -398,6 +421,7 @@ const struct inode_operations ext2_dir_inode_operations = { #endif .setattr = ext2_setattr, .get_acl = ext2_get_acl, + .tmpfile = ext2_tmpfile, }; const struct inode_operations ext2_special_inode_operations = { diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 0db73d9dd668..cd950e2331b6 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -54,6 +54,18 @@ static int minix_mknod(struct inode * dir, struct dentry *dentry, umode_t mode, return error; } +static int minix_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + int error; + struct inode *inode = minix_new_inode(dir, mode, &error); + if (inode) { + minix_set_inode(inode, 0); + mark_inode_dirty(inode); + d_tmpfile(dentry, inode); + } + return error; +} + static int minix_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) { @@ -254,4 +266,5 @@ const struct inode_operations minix_dir_inode_operations = { .mknod = minix_mknod, .rename = minix_rename, .getattr = minix_getattr, + .tmpfile = minix_tmpfile, }; diff --git a/fs/namei.c b/fs/namei.c index 9e66ca32fba0..21321faef876 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3003,6 +3003,61 @@ static int do_last(struct nameidata *nd, struct path *path, goto retry_lookup; } +static int do_tmpfile(int dfd, struct filename *pathname, + struct nameidata *nd, int flags, + const struct open_flags *op, + struct file *file, int *opened) +{ + static const struct qstr name = QSTR_INIT("/", 1); + struct dentry *dentry, *child; + struct inode *dir; + int error = path_lookupat(dfd, pathname->name, + flags | LOOKUP_DIRECTORY, nd); + if (unlikely(error)) + return error; + error = mnt_want_write(nd->path.mnt); + if (unlikely(error)) + goto out; + /* we want directory to be writable */ + error = inode_permission(nd->inode, MAY_WRITE | MAY_EXEC); + if (error) + goto out2; + dentry = nd->path.dentry; + dir = dentry->d_inode; + if (!dir->i_op->tmpfile) { + error = -EOPNOTSUPP; + goto out2; + } + child = d_alloc(dentry, &name); + if (unlikely(!child)) { + error = -ENOMEM; + goto out2; + } + nd->flags &= ~LOOKUP_DIRECTORY; + nd->flags |= op->intent; + dput(nd->path.dentry); + nd->path.dentry = child; + error = dir->i_op->tmpfile(dir, nd->path.dentry, op->mode); + if (error) + goto out2; + audit_inode(pathname, nd->path.dentry, 0); + error = may_open(&nd->path, op->acc_mode, op->open_flag); + if (error) + goto out2; + file->f_path.mnt = nd->path.mnt; + error = finish_open(file, nd->path.dentry, NULL, opened); + if (error) + goto out2; + error = open_check_o_direct(file); + if (error) + fput(file); +out2: + mnt_drop_write(nd->path.mnt); +out: + path_put(&nd->path); + return error; +} + static struct file *path_openat(int dfd, struct filename *pathname, struct nameidata *nd, const struct open_flags *op, int flags) { @@ -3018,6 +3073,11 @@ static struct file *path_openat(int dfd, struct filename *pathname, file->f_flags = op->open_flag; + if (unlikely(file->f_flags & O_TMPFILE)) { + error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened); + goto out; + } + error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base); if (unlikely(error)) goto out; diff --git a/fs/open.c b/fs/open.c index 4bf18067c8e5..bbce2813a8c3 100644 --- a/fs/open.c +++ b/fs/open.c @@ -839,11 +839,15 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o if (flags & __O_SYNC) flags |= O_DSYNC; - /* - * If we have O_PATH in the open flag. Then we - * cannot have anything other than the below set of flags - */ - if (flags & O_PATH) { + if (flags & O_TMPFILE) { + if (!(flags & O_CREAT)) + return -EINVAL; + acc_mode = MAY_OPEN | ACC_MODE(flags); + } else if (flags & O_PATH) { + /* + * If we have O_PATH in the open flag. Then we + * cannot have anything other than the below set of flags + */ flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH; acc_mode = 0; } else { diff --git a/include/linux/dcache.h b/include/linux/dcache.h index f576f8a981d3..5e150d3731cc 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -247,6 +247,8 @@ extern struct dentry * d_make_root(struct inode *); /* - the ramfs-type tree */ extern void d_genocide(struct dentry *); +extern void d_tmpfile(struct dentry *, struct inode *); + extern struct dentry *d_find_alias(struct inode *); extern void d_prune_aliases(struct inode *); diff --git a/include/linux/fs.h b/include/linux/fs.h index f14d780d8145..0ffe99bfa975 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1592,6 +1592,7 @@ struct inode_operations { int (*atomic_open)(struct inode *, struct dentry *, struct file *, unsigned open_flag, umode_t create_mode, int *opened); + int (*tmpfile) (struct inode *, struct dentry *, umode_t); } ____cacheline_aligned; ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h index a48937d4a5ea..06632beaa6d5 100644 --- a/include/uapi/asm-generic/fcntl.h +++ b/include/uapi/asm-generic/fcntl.h @@ -84,6 +84,10 @@ #define O_PATH 010000000 #endif +#ifndef O_TMPFILE +#define O_TMPFILE 020000000 +#endif + #ifndef O_NDELAY #define O_NDELAY O_NONBLOCK #endif diff --git a/mm/shmem.c b/mm/shmem.c index 87e496fc4590..ef0bba3c177c 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2047,6 +2047,37 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) return error; } +static int +shmem_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + struct inode *inode; + int error = -ENOSPC; + + inode = shmem_get_inode(dir->i_sb, dir, mode, 0, VM_NORESERVE); + if (inode) { + error = security_inode_init_security(inode, dir, + NULL, + shmem_initxattrs, NULL); + if (error) { + if (error != -EOPNOTSUPP) { + iput(inode); + return error; + } + } +#ifdef CONFIG_TMPFS_POSIX_ACL + error = generic_acl_init(inode, dir); + if (error) { + iput(inode); + return error; + } +#else + error = 0; +#endif + d_tmpfile(dentry, inode); + } + return error; +} + static int shmem_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { int error; @@ -2807,6 +2838,7 @@ static const struct inode_operations shmem_dir_inode_operations = { .rmdir = shmem_rmdir, .mknod = shmem_mknod, .rename = shmem_rename, + .tmpfile = shmem_tmpfile, #endif #ifdef CONFIG_TMPFS_XATTR .setxattr = shmem_setxattr, From 2422ac7fcd45507b26b396d5cd1e918eade5bbcb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 11 Jun 2013 08:34:36 +0400 Subject: [PATCH 4/8] allow the temp files created by open() to be linked to O_TMPFILE | O_CREAT => linkat() with AT_SYMLINK_FOLLOW and /proc/self/fd/ as oldpath (i.e. flink()) will create a link O_TMPFILE | O_CREAT | O_EXCL => ENOENT on attempt to link those guys Change-Id: I5e28485680c3320cd0fccc0ba1bea8b963fca7fe Signed-off-by: Al Viro --- fs/inode.c | 4 +++- fs/namei.c | 16 ++++++++++++++-- include/linux/fs.h | 1 + 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index eb66712897d6..06d3f378285e 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -333,8 +333,10 @@ EXPORT_SYMBOL(set_nlink); */ void inc_nlink(struct inode *inode) { - if (WARN_ON(inode->i_nlink == 0)) + if (unlikely(inode->i_nlink == 0)) { + WARN_ON(!(inode->i_state & I_LINKABLE)); atomic_long_dec(&inode->i_sb->s_remove_count); + } inode->__i_nlink++; } diff --git a/fs/namei.c b/fs/namei.c index 21321faef876..e09e7f0135f4 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3049,8 +3049,14 @@ static int do_tmpfile(int dfd, struct filename *pathname, if (error) goto out2; error = open_check_o_direct(file); - if (error) + if (error) { fput(file); + } else if (!(op->open_flag & O_EXCL)) { + struct inode *inode = file_inode(file); + spin_lock(&inode->i_lock); + inode->i_state |= I_LINKABLE; + spin_unlock(&inode->i_lock); + } out2: mnt_drop_write(nd->path.mnt); out: @@ -3771,12 +3777,18 @@ int vfs_link2(struct vfsmount *mnt, struct dentry *old_dentry, struct inode *dir mutex_lock(&inode->i_mutex); /* Make sure we don't allow creating hardlink to an unlinked file */ - if (inode->i_nlink == 0) + if (inode->i_nlink == 0 && !(inode->i_state & I_LINKABLE)) error = -ENOENT; else if (max_links && inode->i_nlink >= max_links) error = -EMLINK; else error = dir->i_op->link(old_dentry, dir, new_dentry); + + if (!error && (inode->i_state & I_LINKABLE)) { + spin_lock(&inode->i_lock); + inode->i_state &= ~I_LINKABLE; + spin_unlock(&inode->i_lock); + } mutex_unlock(&inode->i_mutex); if (!error) fsnotify_link(dir, inode, new_dentry); diff --git a/include/linux/fs.h b/include/linux/fs.h index 0ffe99bfa975..939514738d2f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1760,6 +1760,7 @@ struct super_operations { #define I_REFERENCED (1 << 8) #define __I_DIO_WAKEUP 9 #define I_DIO_WAKEUP (1 << I_DIO_WAKEUP) +#define I_LINKABLE (1 << 10) #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) From f05a3d3e749619fec6334b13388bbf5c27402614 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 13 Jul 2013 13:26:37 +0400 Subject: [PATCH 5/8] Safer ABI for O_TMPFILE [suggested by Rasmus Villemoes] make O_DIRECTORY | O_RDWR part of O_TMPFILE; that will fail on old kernels in a lot more cases than what I came up with. And make sure O_CREAT doesn't get there... Change-Id: Iaa3c8b487d44515b539150bdb5d0b749b87d3ea2 Signed-off-by: Al Viro --- arch/alpha/include/uapi/asm/fcntl.h | 2 +- arch/parisc/include/uapi/asm/fcntl.h | 2 +- arch/sparc/include/uapi/asm/fcntl.h | 2 +- fs/namei.c | 2 +- fs/open.c | 4 ++-- include/uapi/asm-generic/fcntl.h | 8 ++++++-- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h index dfdadb0b4bef..09f49a6b87d1 100644 --- a/arch/alpha/include/uapi/asm/fcntl.h +++ b/arch/alpha/include/uapi/asm/fcntl.h @@ -32,7 +32,7 @@ #define O_SYNC (__O_SYNC|O_DSYNC) #define O_PATH 040000000 -#define O_TMPFILE 0100000000 +#define __O_TMPFILE 0100000000 #define F_GETLK 7 #define F_SETLK 8 diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h index cc61c475f277..34a46cbc76ed 100644 --- a/arch/parisc/include/uapi/asm/fcntl.h +++ b/arch/parisc/include/uapi/asm/fcntl.h @@ -20,7 +20,7 @@ #define O_INVISIBLE 004000000 /* invisible I/O, for DMAPI/XDSM */ #define O_PATH 020000000 -#define O_TMPFILE 040000000 +#define __O_TMPFILE 040000000 #define F_GETLK64 8 #define F_SETLK64 9 diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h index d73e5e008b0d..7e8ace5bf760 100644 --- a/arch/sparc/include/uapi/asm/fcntl.h +++ b/arch/sparc/include/uapi/asm/fcntl.h @@ -35,7 +35,7 @@ #define O_SYNC (__O_SYNC|O_DSYNC) #define O_PATH 0x1000000 -#define O_TMPFILE 0x2000000 +#define __O_TMPFILE 0x2000000 #define F_GETOWN 5 /* for sockets. */ #define F_SETOWN 6 /* for sockets. */ diff --git a/fs/namei.c b/fs/namei.c index e09e7f0135f4..773f218bbb76 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3079,7 +3079,7 @@ static struct file *path_openat(int dfd, struct filename *pathname, file->f_flags = op->open_flag; - if (unlikely(file->f_flags & O_TMPFILE)) { + if (unlikely(file->f_flags & __O_TMPFILE)) { error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened); goto out; } diff --git a/fs/open.c b/fs/open.c index bbce2813a8c3..5b259bf428de 100644 --- a/fs/open.c +++ b/fs/open.c @@ -839,8 +839,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o if (flags & __O_SYNC) flags |= O_DSYNC; - if (flags & O_TMPFILE) { - if (!(flags & O_CREAT)) + if (flags & __O_TMPFILE) { + if ((flags & O_TMPFILE_MASK) != O_TMPFILE) return -EINVAL; acc_mode = MAY_OPEN | ACC_MODE(flags); } else if (flags & O_PATH) { diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h index 06632beaa6d5..05ac354e124d 100644 --- a/include/uapi/asm-generic/fcntl.h +++ b/include/uapi/asm-generic/fcntl.h @@ -84,10 +84,14 @@ #define O_PATH 010000000 #endif -#ifndef O_TMPFILE -#define O_TMPFILE 020000000 +#ifndef __O_TMPFILE +#define __O_TMPFILE 020000000 #endif +/* a horrid kludge trying to make sure that this will fail on old kernels */ +#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY | O_RDWR) +#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT | O_ACCMODE) + #ifndef O_NDELAY #define O_NDELAY O_NONBLOCK #endif From 6738b080f5a0ecde1c7bd2df43bac8223e441d91 Mon Sep 17 00:00:00 2001 From: Eric Rannaud Date: Thu, 30 Oct 2014 01:51:01 -0700 Subject: [PATCH 6/8] fs: allow open(dir, O_TMPFILE|..., 0) with mode 0 The man page for open(2) indicates that when O_CREAT is specified, the 'mode' argument applies only to future accesses to the file: Note that this mode applies only to future accesses of the newly created file; the open() call that creates a read-only file may well return a read/write file descriptor. The man page for open(2) implies that 'mode' is treated identically by O_CREAT and O_TMPFILE. O_TMPFILE, however, behaves differently: int fd = open("/tmp", O_TMPFILE | O_RDWR, 0); assert(fd == -1); assert(errno == EACCES); int fd = open("/tmp", O_TMPFILE | O_RDWR, 0600); assert(fd > 0); For O_CREAT, do_last() sets acc_mode to MAY_OPEN only: if (*opened & FILE_CREATED) { /* Don't check for write permission, don't truncate */ open_flag &= ~O_TRUNC; will_truncate = false; acc_mode = MAY_OPEN; path_to_nameidata(path, nd); goto finish_open_created; } But for O_TMPFILE, do_tmpfile() passes the full op->acc_mode to may_open(). This patch lines up the behavior of O_TMPFILE with O_CREAT. After the inode is created, may_open() is called with acc_mode = MAY_OPEN, in do_tmpfile(). A different, but related glibc bug revealed the discrepancy: https://sourceware.org/bugzilla/show_bug.cgi?id=17523 The glibc lazily loads the 'mode' argument of open() and openat() using va_arg() only if O_CREAT is present in 'flags' (to support both the 2 argument and the 3 argument forms of open; same idea for openat()). However, the glibc ignores the 'mode' argument if O_TMPFILE is in 'flags'. On x86_64, for open(), it magically works anyway, as 'mode' is in RDX when entering open(), and is still in RDX on SYSCALL, which is where the kernel looks for the 3rd argument of a syscall. But openat() is not quite so lucky: 'mode' is in RCX when entering the glibc wrapper for openat(), while the kernel looks for the 4th argument of a syscall in R10. Indeed, the syscall calling convention differs from the regular calling convention in this respect on x86_64. So the kernel sees mode = 0 when trying to use glibc openat() with O_TMPFILE, and fails with EACCES. Change-Id: Ib052bbc6fcc68d3060f91732a78ddbff6f71e0a6 Signed-off-by: Eric Rannaud Acked-by: Andy Lutomirski Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds --- fs/namei.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index 773f218bbb76..b1ed4da38e65 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3041,7 +3041,8 @@ static int do_tmpfile(int dfd, struct filename *pathname, if (error) goto out2; audit_inode(pathname, nd->path.dentry, 0); - error = may_open(&nd->path, op->acc_mode, op->open_flag); + /* Don't check for other permissions, the inode was just created */ + error = may_open(&nd->path, MAY_OPEN, op->open_flag); if (error) goto out2; file->f_path.mnt = nd->path.mnt; From 0342f3a7c7d95dae7e7864efc3bb9cce02752319 Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Mon, 3 Sep 2018 19:11:39 -0700 Subject: [PATCH 7/8] uapi: Define __BITS_PER_LONG based on compiler target * We may compile 32-bit ARM code against these kernel headers in many situations, so provide a compiler-defined method of obtaining the width of long. Change-Id: Iac5e48200d70f1258ab3caca1a8f1eb6e8f7f2d3 --- arch/arm64/include/uapi/asm/bitsperlong.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/include/uapi/asm/bitsperlong.h b/arch/arm64/include/uapi/asm/bitsperlong.h index fce9c2924fa3..71f93d50bb2d 100644 --- a/arch/arm64/include/uapi/asm/bitsperlong.h +++ b/arch/arm64/include/uapi/asm/bitsperlong.h @@ -16,7 +16,11 @@ #ifndef __ASM_BITSPERLONG_H #define __ASM_BITSPERLONG_H +#ifdef __aarch64__ #define __BITS_PER_LONG 64 +#else +#define __BITS_PER_LONG 32 +#endif #include From 59ed204f2fa4266526af120e34e8c5af51846bae Mon Sep 17 00:00:00 2001 From: Utkarsh Saxena Date: Wed, 11 Jan 2017 16:30:00 +0530 Subject: [PATCH 8/8] nf_conntrack: Null pointer check added prior deleting sip node Prior to null pointer check, SIP node was deleted from the list a null pointer check is added to confront the exception. Bug: 111529827 Change-Id: Ia12fa468eed7d1a91fad96840fa27cb0e4e208a8 Acked-by: Rishav LNU Signed-off-by: Utkarsh Saxena --- net/netfilter/nf_conntrack_core.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 36fdef85e98e..ad8864eb01b2 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -222,15 +222,15 @@ destroy_conntrack(struct nf_conntrack *nfct) spin_lock_bh(&nf_conntrack_lock); - list_for_each_safe(sip_node_list, sip_node_save_list, - &ct->sip_segment_list) - { - sip_node = list_entry(sip_node_list, struct sip_list, list); - pr_debug("freeing item in the SIP list\n"); - list_del(&(sip_node->list)); - kfree(sip_node); - } - + pr_debug("freeing item in the SIP list\n"); + if (ct->sip_segment_list.next != NULL) + list_for_each_safe(sip_node_list, sip_node_save_list, + &ct->sip_segment_list) { + sip_node = list_entry(sip_node_list, + struct sip_list, list); + list_del(&sip_node->list); + kfree(sip_node); + } /* Expectations will have been removed in clean_from_lists, * except TFTP can create an expectation on the first packet, * before connection is in the list, so we need to clean here,