]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 3 Jul 2015 22:20:57 +0000 (15:20 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 3 Jul 2015 22:20:57 +0000 (15:20 -0700)
Pull user namespace updates from Eric Biederman:
 "Long ago and far away when user namespaces where young it was realized
  that allowing fresh mounts of proc and sysfs with only user namespace
  permissions could violate the basic rule that only root gets to decide
  if proc or sysfs should be mounted at all.

  Some hacks were put in place to reduce the worst of the damage could
  be done, and the common sense rule was adopted that fresh mounts of
  proc and sysfs should allow no more than bind mounts of proc and
  sysfs.  Unfortunately that rule has not been fully enforced.

  There are two kinds of gaps in that enforcement.  Only filesystems
  mounted on empty directories of proc and sysfs should be ignored but
  the test for empty directories was insufficient.  So in my tree
  directories on proc, sysctl and sysfs that will always be empty are
  created specially.  Every other technique is imperfect as an ordinary
  directory can have entries added even after a readdir returns and
  shows that the directory is empty.  Special creation of directories
  for mount points makes the code in the kernel a smidge clearer about
  it's purpose.  I asked container developers from the various container
  projects to help test this and no holes were found in the set of mount
  points on proc and sysfs that are created specially.

  This set of changes also starts enforcing the mount flags of fresh
  mounts of proc and sysfs are consistent with the existing mount of
  proc and sysfs.  I expected this to be the boring part of the work but
  unfortunately unprivileged userspace winds up mounting fresh copies of
  proc and sysfs with noexec and nosuid clear when root set those flags
  on the previous mount of proc and sysfs.  So for now only the atime,
  read-only and nodev attributes which userspace happens to keep
  consistent are enforced.  Dealing with the noexec and nosuid
  attributes remains for another time.

  This set of changes also addresses an issue with how open file
  descriptors from /proc/<pid>/ns/* are displayed.  Recently readlink of
  /proc/<pid>/fd has been triggering a WARN_ON that has not been
  meaningful since it was added (as all of the code in the kernel was
  converted) and is not now actively wrong.

  There is also a short list of issues that have not been fixed yet that
  I will mention briefly.

  It is possible to rename a directory from below to above a bind mount.
  At which point any directory pointers below the renamed directory can
  be walked up to the root directory of the filesystem.  With user
  namespaces enabled a bind mount of the bind mount can be created
  allowing the user to pick a directory whose children they can rename
  to outside of the bind mount.  This is challenging to fix and doubly
  so because all obvious solutions must touch code that is in the
  performance part of pathname resolution.

  As mentioned above there is also a question of how to ensure that
  developers by accident or with purpose do not introduce exectuable
  files on sysfs and proc and in doing so introduce security regressions
  in the current userspace that will not be immediately obvious and as
  such are likely to require breaking userspace in painful ways once
  they are recognized"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace:
  vfs: Remove incorrect debugging WARN in prepend_path
  mnt: Update fs_fully_visible to test for permanently empty directories
  sysfs: Create mountpoints with sysfs_create_mount_point
  sysfs: Add support for permanently empty directories to serve as mount points.
  kernfs: Add support for always empty directories.
  proc: Allow creating permanently empty directories that serve as mount points
  sysctl: Allow creating permanently empty directories that serve as mountpoints.
  fs: Add helper functions for permanently empty directories.
  vfs: Ignore unlocked mounts in fs_fully_visible
  mnt: Modify fs_fully_visible to deal with locked ro nodev and atime
  mnt: Refactor the logic for mounting sysfs and proc in a user namespace

14 files changed:
1  2 
drivers/firmware/efi/efi.c
fs/configfs/mount.c
fs/dcache.c
fs/debugfs/inode.c
fs/fuse/inode.c
fs/kernfs/dir.c
fs/libfs.c
fs/namespace.c
fs/proc/inode.c
include/linux/fs.h
include/linux/kernfs.h
kernel/cgroup.c
kernel/sysctl.c
security/smack/smackfs.c

index ca617f40574ac2bb8e5697b858a1c52f93c8fad9,e14363d126906b1b56cd7b602b6d7b51c90cd046..9fa8084a7c8d7d9e5aff23bdd372af512e39047a
@@@ -65,8 -64,7 +65,7 @@@ static int __init parse_efi_cmdline(cha
  }
  early_param("efi", parse_efi_cmdline);
  
 -static struct kobject *efi_kobj;
 +struct kobject *efi_kobj;
- static struct kobject *efivars_kobj;
  
  /*
   * Let's not leave out systab information that snuck into
Simple merge
diff --cc fs/dcache.c
Simple merge
Simple merge
diff --cc fs/fuse/inode.c
Simple merge
diff --cc fs/kernfs/dir.c
Simple merge
diff --cc fs/libfs.c
index 65e1feca8b982c55bff37e5a85529f8cb0d4121e,02813592e1216a425c810fdbb846c7f5281812b8..88a4cb418756c29c5273432ac0f364c340c7f6f7
@@@ -1097,14 -1094,98 +1097,109 @@@ simple_nosetlease(struct file *filp, lo
  }
  EXPORT_SYMBOL(simple_nosetlease);
  
 +const char *simple_follow_link(struct dentry *dentry, void **cookie)
 +{
 +      return d_inode(dentry)->i_link;
 +}
 +EXPORT_SYMBOL(simple_follow_link);
 +
 +const struct inode_operations simple_symlink_inode_operations = {
 +      .follow_link = simple_follow_link,
 +      .readlink = generic_readlink
 +};
 +EXPORT_SYMBOL(simple_symlink_inode_operations);
+ /*
+  * Operations for a permanently empty directory.
+  */
+ static struct dentry *empty_dir_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
+ {
+       return ERR_PTR(-ENOENT);
+ }
+ static int empty_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
+                                struct kstat *stat)
+ {
+       struct inode *inode = d_inode(dentry);
+       generic_fillattr(inode, stat);
+       return 0;
+ }
+ static int empty_dir_setattr(struct dentry *dentry, struct iattr *attr)
+ {
+       return -EPERM;
+ }
+ static int empty_dir_setxattr(struct dentry *dentry, const char *name,
+                             const void *value, size_t size, int flags)
+ {
+       return -EOPNOTSUPP;
+ }
+ static ssize_t empty_dir_getxattr(struct dentry *dentry, const char *name,
+                                 void *value, size_t size)
+ {
+       return -EOPNOTSUPP;
+ }
+ static int empty_dir_removexattr(struct dentry *dentry, const char *name)
+ {
+       return -EOPNOTSUPP;
+ }
+ static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size)
+ {
+       return -EOPNOTSUPP;
+ }
+ static const struct inode_operations empty_dir_inode_operations = {
+       .lookup         = empty_dir_lookup,
+       .permission     = generic_permission,
+       .setattr        = empty_dir_setattr,
+       .getattr        = empty_dir_getattr,
+       .setxattr       = empty_dir_setxattr,
+       .getxattr       = empty_dir_getxattr,
+       .removexattr    = empty_dir_removexattr,
+       .listxattr      = empty_dir_listxattr,
+ };
+ static loff_t empty_dir_llseek(struct file *file, loff_t offset, int whence)
+ {
+       /* An empty directory has two entries . and .. at offsets 0 and 1 */
+       return generic_file_llseek_size(file, offset, whence, 2, 2);
+ }
+ static int empty_dir_readdir(struct file *file, struct dir_context *ctx)
+ {
+       dir_emit_dots(file, ctx);
+       return 0;
+ }
+ static const struct file_operations empty_dir_operations = {
+       .llseek         = empty_dir_llseek,
+       .read           = generic_read_dir,
+       .iterate        = empty_dir_readdir,
+       .fsync          = noop_fsync,
+ };
+ void make_empty_dir_inode(struct inode *inode)
+ {
+       set_nlink(inode, 2);
+       inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
+       inode->i_uid = GLOBAL_ROOT_UID;
+       inode->i_gid = GLOBAL_ROOT_GID;
+       inode->i_rdev = 0;
+       inode->i_size = 2;
+       inode->i_blkbits = PAGE_SHIFT;
+       inode->i_blocks = 0;
+       inode->i_op = &empty_dir_inode_operations;
+       inode->i_fop = &empty_dir_operations;
+ }
+ bool is_empty_dir_inode(struct inode *inode)
+ {
+       return (inode->i_fop == &empty_dir_operations) &&
+               (inode->i_op == &empty_dir_inode_operations);
+ }
diff --cc fs/namespace.c
Simple merge
diff --cc fs/proc/inode.c
Simple merge
Simple merge
Simple merge
diff --cc kernel/cgroup.c
Simple merge
diff --cc kernel/sysctl.c
Simple merge
Simple merge