aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorSuraj Das <surajdazz@gmail.com>2017-06-25 19:07:06 +0530
committerSuraj Das <surajdazz@gmail.com>2017-06-25 19:15:40 +0530
commit6e033ebda94e620277a569625745cf21c749efdb (patch)
tree641e80dabecde9fd9108b654bf43828d78632509 /fs
parentfa097959467283e96988ba548a20ccb3ec27c0c1 (diff)
parent262196005747d5e8b4106e92adae3749e8686240 (diff)
Merge branch 'cm-14.1' of https://github.com/LineageOS/android_kernel_oneplus_msm8974 into n7.1HEADn7.1
Diffstat (limited to 'fs')
-rw-r--r--fs/9p/acl.c40
-rw-r--r--fs/btrfs/acl.c4
-rw-r--r--fs/ecryptfs/file.c9
-rw-r--r--fs/ecryptfs/main.c7
-rw-r--r--fs/exec.c5
-rw-r--r--fs/ext2/acl.c12
-rw-r--r--fs/ext3/acl.c12
-rw-r--r--fs/ext4/acl.c12
-rw-r--r--fs/f2fs/acl.c4
-rw-r--r--fs/generic_acl.c8
-rw-r--r--fs/gfs2/acl.c11
-rw-r--r--fs/jffs2/acl.c9
-rw-r--r--fs/jfs/xattr.c6
-rw-r--r--fs/namei.c10
-rw-r--r--fs/ocfs2/acl.c18
-rw-r--r--fs/posix_acl.c29
-rw-r--r--fs/proc/array.c10
-rw-r--r--fs/readdir.c20
-rw-r--r--fs/reiserfs/xattr_acl.c8
-rw-r--r--fs/sdcardfs/main.c7
-rw-r--r--fs/xfs/xfs_acl.c13
21 files changed, 148 insertions, 106 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 9a1d4263075..a4188cfcc9f 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -319,32 +319,26 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
case ACL_TYPE_ACCESS:
name = POSIX_ACL_XATTR_ACCESS;
if (acl) {
- umode_t mode = inode->i_mode;
- retval = posix_acl_equiv_mode(acl, &mode);
- if (retval < 0)
+ struct iattr iattr;
+
+ retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
+ if (retval)
goto err_out;
- else {
- struct iattr iattr;
- if (retval == 0) {
- /*
- * ACL can be represented
- * by the mode bits. So don't
- * update ACL.
- */
- acl = NULL;
- value = NULL;
- size = 0;
- }
- /* Updte the mode bits */
- iattr.ia_mode = ((mode & S_IALLUGO) |
- (inode->i_mode & ~S_IALLUGO));
- iattr.ia_valid = ATTR_MODE;
- /* FIXME should we update ctime ?
- * What is the following setxattr update the
- * mode ?
+ if (!acl) {
+ /*
+ * ACL can be represented
+ * by the mode bits. So don't
+ * update ACL.
*/
- v9fs_vfs_setattr_dotl(dentry, &iattr);
+ value = NULL;
+ size = 0;
}
+ iattr.ia_valid = ATTR_MODE;
+ /* FIXME should we update ctime ?
+ * What is the following setxattr update the
+ * mode ?
+ */
+ v9fs_vfs_setattr_dotl(dentry, &iattr);
}
break;
case ACL_TYPE_DEFAULT:
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 89b156d85d6..9f55b545ea4 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -118,8 +118,8 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans,
case ACL_TYPE_ACCESS:
name = POSIX_ACL_XATTR_ACCESS;
if (acl) {
- ret = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (ret < 0)
+ ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (ret)
return ret;
}
ret = 0;
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 805be43324a..ef830491326 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -146,6 +146,15 @@ static int read_or_initialize_metadata(struct dentry *dentry)
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
struct ecryptfs_crypt_stat *crypt_stat;
int rc;
+ struct file *lower_file = ecryptfs_file_to_lower(file);
+
+ /*
+ * Don't allow mmap on top of file systems that don't support it
+ * natively. If FILESYSTEM_MAX_STACK_DEPTH > 2 or ecryptfs
+ * allows recursive mounting, this will need to be extended.
+ */
+ if (!lower_file->f_op->mmap)
+ return -ENODEV;
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
mount_crypt_stat = &ecryptfs_superblock_to_private(
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 93b7bec021b..81e69c7a74b 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -576,6 +576,13 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
s->s_maxbytes = path.dentry->d_sb->s_maxbytes;
s->s_blocksize = path.dentry->d_sb->s_blocksize;
s->s_magic = ECRYPTFS_SUPER_MAGIC;
+ s->s_stack_depth = path.dentry->d_sb->s_stack_depth + 1;
+
+ rc = -EINVAL;
+ if (s->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
+ pr_err("eCryptfs: maximum fs stacking depth exceeded\n");
+ goto out_free;
+ }
inode = ecryptfs_get_inode(path.dentry->d_inode, s);
rc = PTR_ERR(inode);
diff --git a/fs/exec.c b/fs/exec.c
index a4d05ce9248..73e9bd4d46e 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1591,6 +1591,11 @@ static int do_execve_common(const char *filename,
if (retval < 0)
goto out;
+ if (d_is_su(file->f_dentry) && capable(CAP_SYS_ADMIN)) {
+ current->flags |= PF_SU;
+ su_exec();
+ }
+
/* execve succeeded */
current->fs->in_exec = 0;
current->in_execve = 0;
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 35d6a3cfd9f..e38a9b61af3 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -194,15 +194,11 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
case ACL_TYPE_ACCESS:
name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (error < 0)
+ error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (error)
return error;
- else {
- inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
- if (error == 0)
- acl = NULL;
- }
+ inode->i_ctime = CURRENT_TIME_SEC;
+ mark_inode_dirty(inode);
}
break;
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index c76832c8d19..f3326ca3415 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -193,15 +193,11 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
case ACL_TYPE_ACCESS:
name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (error < 0)
+ error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (error)
return error;
- else {
- inode->i_ctime = CURRENT_TIME_SEC;
- ext3_mark_inode_dirty(handle, inode);
- if (error == 0)
- acl = NULL;
- }
+ inode->i_ctime = CURRENT_TIME_SEC;
+ ext3_mark_inode_dirty(handle, inode);
}
break;
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 8535c45dfce..5d419a496d9 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -198,15 +198,11 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type,
case ACL_TYPE_ACCESS:
name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (error < 0)
+ error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (error)
return error;
- else {
- inode->i_ctime = ext4_current_time(inode);
- ext4_mark_inode_dirty(handle, inode);
- if (error == 0)
- acl = NULL;
- }
+ inode->i_ctime = ext4_current_time(inode);
+ ext4_mark_inode_dirty(handle, inode);
}
break;
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index f431f992555..962e4e98e8a 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -211,8 +211,8 @@ static int f2fs_set_acl(struct inode *inode, int type,
case ACL_TYPE_ACCESS:
name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (error < 0)
+ error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (error)
return error;
set_acl_inode(inode, inode->i_mode);
if (error == 0)
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
index d0dddaceac5..e9c0746e820 100644
--- a/fs/generic_acl.c
+++ b/fs/generic_acl.c
@@ -87,14 +87,10 @@ generic_acl_set(struct dentry *dentry, const char *name, const void *value,
goto failed;
switch (type) {
case ACL_TYPE_ACCESS:
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (error < 0)
+ error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (error)
goto failed;
inode->i_ctime = CURRENT_TIME;
- if (error == 0) {
- posix_acl_release(acl);
- acl = NULL;
- }
break;
case ACL_TYPE_DEFAULT:
if (!S_ISDIR(inode->i_mode)) {
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 230eb0f005b..846611f2e41 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -274,15 +274,10 @@ static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
if (type == ACL_TYPE_ACCESS) {
umode_t mode = inode->i_mode;
- error = posix_acl_equiv_mode(acl, &mode);
+ error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
- if (error <= 0) {
- posix_acl_release(acl);
- acl = NULL;
-
- if (error < 0)
- return error;
- }
+ if (error)
+ goto out_release;
error = gfs2_set_mode(inode, mode);
if (error)
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 922f146e423..398e5c71c50 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -229,9 +229,10 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
case ACL_TYPE_ACCESS:
xprefix = JFFS2_XPREFIX_ACL_ACCESS;
if (acl) {
- umode_t mode = inode->i_mode;
- rc = posix_acl_equiv_mode(acl, &mode);
- if (rc < 0)
+ umode_t mode;
+
+ rc = posix_acl_update_mode(inode, &mode, &acl);
+ if (rc)
return rc;
if (inode->i_mode != mode) {
struct iattr attr;
@@ -243,8 +244,6 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
if (rc < 0)
return rc;
}
- if (rc == 0)
- acl = NULL;
}
break;
case ACL_TYPE_DEFAULT:
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 26683e15b3a..41a0735314f 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -693,11 +693,11 @@ static int can_set_system_xattr(struct inode *inode, const char *name,
return rc;
}
if (acl) {
- rc = posix_acl_equiv_mode(acl, &inode->i_mode);
+ rc = posix_acl_update_mode(inode, &inode->i_mode, &acl);
posix_acl_release(acl);
- if (rc < 0) {
+ if (rc) {
printk(KERN_ERR
- "posix_acl_equiv_mode returned %d\n",
+ "posix_acl_update_mode returned %d\n",
rc);
return rc;
}
diff --git a/fs/namei.c b/fs/namei.c
index df12b576c21..689339e3e7e 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1800,6 +1800,16 @@ static int path_lookupat(int dfd, const char *name,
}
}
+ if (!err) {
+ struct super_block *sb = nd->inode->i_sb;
+ if (sb->s_flags & MS_RDONLY) {
+ if (d_is_su(nd->path.dentry) && !su_visible()) {
+ path_put(&nd->path);
+ err = -ENOENT;
+ }
+ }
+ }
+
if (base)
fput(base);
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index a7219075b4d..eed868e9a89 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -248,19 +248,13 @@ static int ocfs2_set_acl(handle_t *handle,
name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl) {
umode_t mode = inode->i_mode;
- ret = posix_acl_equiv_mode(acl, &mode);
- if (ret < 0)
+ ret = posix_acl_update_mode(inode, &mode, &acl);
+ if (ret)
+ return ret;
+ ret = ocfs2_acl_set_mode(inode, di_bh,
+ handle, mode);
+ if (ret)
return ret;
- else {
- if (ret == 0)
- acl = NULL;
-
- ret = ocfs2_acl_set_mode(inode, di_bh,
- handle, mode);
- if (ret)
- return ret;
-
- }
}
break;
case ACL_TYPE_DEFAULT:
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 64496020bf1..9607a1df282 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -341,6 +341,35 @@ static int posix_acl_create_masq(struct posix_acl *acl, umode_t *mode_p)
return not_equiv;
}
+/**
+ * posix_acl_update_mode - update mode in set_acl
+ *
+ * Update the file mode when setting an ACL: compute the new file permission
+ * bits based on the ACL. In addition, if the ACL is equivalent to the new
+ * file mode, set *acl to NULL to indicate that no ACL should be set.
+ *
+ * As with chmod, clear the setgit bit if the caller is not in the owning group
+ * or capable of CAP_FSETID (see inode_change_ok).
+ *
+ * Called from set_acl inode operations.
+ */
+int posix_acl_update_mode(struct inode *inode, umode_t *mode_p,
+ struct posix_acl **acl)
+{
+ umode_t mode = inode->i_mode;
+ int error;
+
+ error = posix_acl_update_mode(inode, &inode->i_mode, acl);
+ if (error)
+ return error;
+ if (!in_group_p(inode->i_gid) &&
+ !capable(CAP_FSETID))
+ mode &= ~S_ISGID;
+ *mode_p = mode;
+ return 0;
+}
+EXPORT_SYMBOL(posix_acl_update_mode);
+
/*
* Modify the ACL for the chmod syscall.
*/
diff --git a/fs/proc/array.c b/fs/proc/array.c
index e7bb0fed720..607f80c8d50 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -166,16 +166,16 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
int g;
struct fdtable *fdt = NULL;
const struct cred *cred;
- pid_t ppid, tpid;
+ pid_t ppid = 0, tpid = 0;
+ struct task_struct *leader = NULL;
rcu_read_lock();
- ppid = pid_alive(p) ?
- task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
- tpid = 0;
if (pid_alive(p)) {
struct task_struct *tracer = ptrace_parent(p);
if (tracer)
tpid = task_pid_nr_ns(tracer, ns);
+ ppid = task_tgid_nr_ns(rcu_dereference(p->real_parent), ns);
+ leader = p->group_leader;
}
cred = get_task_cred(p);
seq_printf(m,
@@ -187,7 +187,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
"Uid:\t%d\t%d\t%d\t%d\n"
"Gid:\t%d\t%d\t%d\t%d\n",
get_task_state(p),
- task_tgid_nr_ns(p, ns),
+ leader ? task_pid_nr_ns(leader, ns) : 0,
pid_nr_ns(pid, ns),
ppid, tpid,
cred->uid, cred->euid, cred->suid, cred->fsuid,
diff --git a/fs/readdir.c b/fs/readdir.c
index cc0a8227cdd..536054080bc 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -47,6 +47,14 @@ out:
EXPORT_SYMBOL(vfs_readdir);
+static bool hide_name(const char *name, int namlen)
+{
+ if (namlen == 2 && !memcmp(name, "su", 2))
+ if (!su_visible())
+ return true;
+ return false;
+}
+
/*
* Traditional linux readdir() handling..
*
@@ -68,6 +76,7 @@ struct old_linux_dirent {
struct readdir_callback {
struct old_linux_dirent __user * dirent;
int result;
+ bool romnt;
};
static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset,
@@ -84,6 +93,8 @@ static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset
buf->result = -EOVERFLOW;
return -EOVERFLOW;
}
+ if (hide_name(name, namlen) && buf->romnt)
+ return 0;
buf->result++;
dirent = buf->dirent;
if (!access_ok(VERIFY_WRITE, dirent,
@@ -116,6 +127,7 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
buf.result = 0;
buf.dirent = dirent;
+ buf.romnt = (file->f_path.dentry->d_sb->s_flags & MS_RDONLY);
error = vfs_readdir(file, fillonedir, &buf);
if (buf.result)
@@ -144,6 +156,7 @@ struct getdents_callback {
struct linux_dirent __user * previous;
int count;
int error;
+ bool romnt;
};
static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
@@ -163,6 +176,8 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
buf->error = -EOVERFLOW;
return -EOVERFLOW;
}
+ if (hide_name(name, namlen) && buf->romnt)
+ return 0;
dirent = buf->previous;
if (dirent) {
if (__put_user(offset, &dirent->d_off))
@@ -210,6 +225,7 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
buf.previous = NULL;
buf.count = count;
buf.error = 0;
+ buf.romnt = (file->f_path.dentry->d_sb->s_flags & MS_RDONLY);
error = vfs_readdir(file, filldir, &buf);
if (error >= 0)
@@ -231,6 +247,7 @@ struct getdents_callback64 {
struct linux_dirent64 __user * previous;
int count;
int error;
+ bool romnt;
};
static int filldir64(void * __buf, const char * name, int namlen, loff_t offset,
@@ -244,6 +261,8 @@ static int filldir64(void * __buf, const char * name, int namlen, loff_t offset,
buf->error = -EINVAL; /* only used if we fail.. */
if (reclen > buf->count)
return -EINVAL;
+ if (hide_name(name, namlen) && buf->romnt)
+ return 0;
dirent = buf->previous;
if (dirent) {
if (__put_user(offset, &dirent->d_off))
@@ -293,6 +312,7 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
buf.previous = NULL;
buf.count = count;
buf.error = 0;
+ buf.romnt = (file->f_path.dentry->d_sb->s_flags & MS_RDONLY);
error = vfs_readdir(file, filldir64, &buf);
if (error >= 0)
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 44474f9b990..502254b6432 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -272,13 +272,9 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
case ACL_TYPE_ACCESS:
name = POSIX_ACL_XATTR_ACCESS;
if (acl) {
- error = posix_acl_equiv_mode(acl, &inode->i_mode);
- if (error < 0)
+ error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+ if (error)
return error;
- else {
- if (error == 0)
- acl = NULL;
- }
}
break;
case ACL_TYPE_DEFAULT:
diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c
index d46970095cb..97375a13ba1 100644
--- a/fs/sdcardfs/main.c
+++ b/fs/sdcardfs/main.c
@@ -223,6 +223,13 @@ static int sdcardfs_read_super(struct super_block *sb, const char *dev_name,
atomic_inc(&lower_sb->s_active);
sdcardfs_set_lower_super(sb, lower_sb);
+ sb->s_stack_depth = lower_sb->s_stack_depth + 1;
+ if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
+ pr_err("sdcardfs: maximum fs stacking depth exceeded\n");
+ err = -EINVAL;
+ goto out_sput;
+ }
+
/* inherit maxbytes from lower file system */
sb->s_maxbytes = lower_sb->s_maxbytes;
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index ac702a6eab9..c0f97c319b7 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -384,16 +384,9 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,
if (type == ACL_TYPE_ACCESS) {
umode_t mode = inode->i_mode;
- error = posix_acl_equiv_mode(acl, &mode);
-
- if (error <= 0) {
- posix_acl_release(acl);
- acl = NULL;
-
- if (error < 0)
- return error;
- }
-
+ error = posix_acl_update_mode(inode, &mode, &acl);
+ if (error)
+ goto out_release;
error = xfs_set_mode(inode, mode);
if (error)
goto out_release;