lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20150209040217.GA23091@linux.vnet.ibm.com>
Date:	Sun, 8 Feb 2015 20:02:17 -0800
From:	"Paul E. McKenney" <paulmck@...ux.vnet.ibm.com>
To:	Iulia Manda <iulia.manda21@...il.com>
Cc:	gnomes@...rguk.ukuu.org.uk, josh@...htriplett.org,
	peterz@...radead.org, mhocko@...e.cz, akpm@...ux-foundation.org,
	linux-kernel@...r.kernel.org, serge.hallyn@...onical.com,
	dvhart@...ux.intel.com, tim.bird@...ymobile.com
Subject: Re: [PATCH v3] kernel: Conditionally support non-root users, groups
 and capabilities

On Fri, Feb 06, 2015 at 02:03:56AM +0200, Iulia Manda wrote:
> There are a lot of embedded systems that run most or all of their functionality
> in init, running as root:root. For these systems, supporting multiple users is
> not necessary.
> 
> This patch adds a new symbol, CONFIG_MULTIUSER, that makes support for non-root
> users, non-root groups, and capabilities optional. It is enabled under
> CONFIG_EXPERT menu.
> 
> When this symbol is not defined, UID and GID are zero in any possible case
> and processes always have all capabilities.
> 
> The following syscalls are compiled out: setuid, setregid, setgid,
> setreuid, setresuid, getresuid, setresgid, getresgid, setgroups, getgroups,
> setfsuid, setfsgid, capget, capset.
> 
> Also, groups.c is compiled out completely.
> 
> This change saves about 25 KB on a defconfig build.
> 
> The kernel was booted in Qemu. All the common functionalities work. Adding
> users/groups is not possible, failing with -ENOSYS.
> 
> Bloat-o-meter output:
> add/remove: 7/87 grow/shrink: 19/397 up/down: 1675/-26325 (-24650)

I presume that v4 will have your Signed-off-by.  ;-)

Testing on my rcutorture setup uncovered an additional required dependency,
please see patch at the end of this email.  With that fix, either separately
or merged into your patch:

Tested-by: Paul E. McKenney <paulmck@...ux.vnet.ibm.com>

One question below about moving the definition of capable().  Either way:

Reviewed-by: Paul E. McKenney <paulmck@...ux.vnet.ibm.com>

> ---
> Changes since v2:
>         - rename symbol;
>         - make SECURITY dependent on MULTIUSER
> 
>  arch/s390/Kconfig                     |    1 +
>  drivers/staging/lustre/lustre/Kconfig |    1 +
>  fs/nfsd/Kconfig                       |    1 +
>  include/linux/capability.h            |   29 +++++++++++++++++++++++++++
>  include/linux/cred.h                  |   23 ++++++++++++++++++----
>  include/linux/uidgid.h                |   12 +++++++++++
>  init/Kconfig                          |   19 +++++++++++++++++-
>  kernel/Makefile                       |    4 +++-
>  kernel/capability.c                   |   35 ++++++++++++++++++---------------
>  kernel/cred.c                         |    3 +++
>  kernel/groups.c                       |    3 ---
>  kernel/sys.c                          |    2 ++
>  kernel/sys_ni.c                       |   14 +++++++++++++
>  net/sunrpc/Kconfig                    |    2 ++
>  security/Kconfig                      |    1 +
>  15 files changed, 125 insertions(+), 25 deletions(-)
> 
> diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
> index 68b68d7..71fb2d1 100644
> --- a/arch/s390/Kconfig
> +++ b/arch/s390/Kconfig
> @@ -324,6 +324,7 @@ config COMPAT
>  	select COMPAT_BINFMT_ELF if BINFMT_ELF
>  	select ARCH_WANT_OLD_COMPAT_IPC
>  	select COMPAT_OLD_SIGACTION
> +	depends on MULTIUSER
>  	help
>  	  Select this option if you want to enable your system kernel to
>  	  handle system-calls from ELF binaries for 31 bit ESA.  This option
> diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig
> index 6725467..62c7bba 100644
> --- a/drivers/staging/lustre/lustre/Kconfig
> +++ b/drivers/staging/lustre/lustre/Kconfig
> @@ -10,6 +10,7 @@ config LUSTRE_FS
>  	select CRYPTO_SHA1
>  	select CRYPTO_SHA256
>  	select CRYPTO_SHA512
> +	depends on MULTIUSER
>  	help
>  	  This option enables Lustre file system client support. Choose Y
>  	  here if you want to access a Lustre file system cluster. To compile
> diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
> index 7339515..df0a5d9 100644
> --- a/fs/nfsd/Kconfig
> +++ b/fs/nfsd/Kconfig
> @@ -6,6 +6,7 @@ config NFSD
>  	select SUNRPC
>  	select EXPORTFS
>  	select NFS_ACL_SUPPORT if NFSD_V2_ACL
> +	depends on MULTIUSER
>  	help
>  	  Choose Y here if you want to allow other computers to access
>  	  files residing on this system using Sun's Network File System
> diff --git a/include/linux/capability.h b/include/linux/capability.h
> index aa93e5e..0c0ae0d 100644
> --- a/include/linux/capability.h
> +++ b/include/linux/capability.h
> @@ -205,6 +205,7 @@ static inline kernel_cap_t cap_raise_nfsd_set(const kernel_cap_t a,
>  			   cap_intersect(permitted, __cap_nfsd_set));
>  }
> 
> +#ifdef CONFIG_MULTIUSER
>  extern bool has_capability(struct task_struct *t, int cap);
>  extern bool has_ns_capability(struct task_struct *t,
>  			      struct user_namespace *ns, int cap);
> @@ -213,6 +214,34 @@ extern bool has_ns_capability_noaudit(struct task_struct *t,
>  				      struct user_namespace *ns, int cap);
>  extern bool capable(int cap);
>  extern bool ns_capable(struct user_namespace *ns, int cap);
> +#else
> +static inline bool has_capability(struct task_struct *t, int cap)
> +{
> +        return true;
> +}
> +static inline bool has_ns_capability(struct task_struct *t,
> +			      struct user_namespace *ns, int cap)
> +{
> +        return true;
> +}
> +static inline bool has_capability_noaudit(struct task_struct *t, int cap)
> +{
> +        return true;
> +}
> +static inline bool has_ns_capability_noaudit(struct task_struct *t,
> +				      struct user_namespace *ns, int cap)
> +{
> +        return true;
> +}
> +static inline bool capable(int cap)
> +{
> +	return true;
> +}
> +static inline bool ns_capable(struct user_namespace *ns, int cap)
> +{
> +	return true;
> +}
> +#endif /* CONFIG_MULTIUSER */
>  extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
>  extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
> 
> diff --git a/include/linux/cred.h b/include/linux/cred.h
> index 2fb2ca2..8b6c083 100644
> --- a/include/linux/cred.h
> +++ b/include/linux/cred.h
> @@ -62,9 +62,27 @@ do {							\
>  		groups_free(group_info);		\
>  } while (0)
> 
> -extern struct group_info *groups_alloc(int);
>  extern struct group_info init_groups;
> +#ifdef CONFIG_MULTIUSER
> +extern struct group_info *groups_alloc(int);
>  extern void groups_free(struct group_info *);
> +
> +extern int in_group_p(kgid_t);
> +extern int in_egroup_p(kgid_t);
> +#else
> +static inline void groups_free(struct group_info *group_info)
> +{
> +}
> +
> +static inline int in_group_p(kgid_t grp)
> +{
> +        return 1;
> +}
> +static inline int in_egroup_p(kgid_t grp)
> +{
> +        return 1;
> +}
> +#endif
>  extern int set_current_groups(struct group_info *);
>  extern void set_groups(struct cred *, struct group_info *);
>  extern int groups_search(const struct group_info *, kgid_t);
> @@ -74,9 +92,6 @@ extern bool may_setgroups(void);
>  #define GROUP_AT(gi, i) \
>  	((gi)->blocks[(i) / NGROUPS_PER_BLOCK][(i) % NGROUPS_PER_BLOCK])
> 
> -extern int in_group_p(kgid_t);
> -extern int in_egroup_p(kgid_t);
> -
>  /*
>   * The security context of a task
>   *
> diff --git a/include/linux/uidgid.h b/include/linux/uidgid.h
> index 2d1f9b6..0ee05da 100644
> --- a/include/linux/uidgid.h
> +++ b/include/linux/uidgid.h
> @@ -29,6 +29,7 @@ typedef struct {
>  #define KUIDT_INIT(value) (kuid_t){ value }
>  #define KGIDT_INIT(value) (kgid_t){ value }
> 
> +#ifdef CONFIG_MULTIUSER
>  static inline uid_t __kuid_val(kuid_t uid)
>  {
>  	return uid.val;
> @@ -38,6 +39,17 @@ static inline gid_t __kgid_val(kgid_t gid)
>  {
>  	return gid.val;
>  }
> +#else
> +static inline uid_t __kuid_val(kuid_t uid)
> +{
> +	return 0;
> +}
> +
> +static inline gid_t __kgid_val(kgid_t gid)
> +{
> +	return 0;
> +}
> +#endif
> 
>  #define GLOBAL_ROOT_UID KUIDT_INIT(0)
>  #define GLOBAL_ROOT_GID KGIDT_INIT(0)
> diff --git a/init/Kconfig b/init/Kconfig
> index 9afb971..b0332c2 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -394,6 +394,7 @@ endchoice
> 
>  config BSD_PROCESS_ACCT
>  	bool "BSD Process Accounting"
> +	depends on MULTIUSER
>  	help
>  	  If you say Y here, a user level program will be able to instruct the
>  	  kernel (via a special system call) to write process accounting
> @@ -420,6 +421,7 @@ config BSD_PROCESS_ACCT_V3
>  config TASKSTATS
>  	bool "Export task/process statistics through netlink"
>  	depends on NET
> +	depends on MULTIUSER
>  	default n
>  	help
>  	  Export selected statistics for tasks/processes through the
> @@ -1140,6 +1142,7 @@ config CHECKPOINT_RESTORE
> 
>  menuconfig NAMESPACES
>  	bool "Namespaces support" if EXPERT
> +	depends on MULTIUSER
>  	default !EXPERT
>  	help
>  	  Provides the way to make tasks work with different objects using
> @@ -1352,11 +1355,25 @@ menuconfig EXPERT
> 
>  config UID16
>  	bool "Enable 16-bit UID system calls" if EXPERT
> -	depends on HAVE_UID16
> +	depends on HAVE_UID16 && MULTIUSER
>  	default y
>  	help
>  	  This enables the legacy 16-bit UID syscall wrappers.
> 
> +config MULTIUSER
> +	bool "Multiple users, groups and capabilities support" if EXPERT
> +	default y
> +	help
> +	  This option enables support for non-root users, groups and
> +	  capabilities.
> +
> +	  If you say N here, all processes will run with UID 0, GID 0, and all
> +	  possible capabilities.  Saying N here also compiles out support for
> +	  system calls related to UIDs, GIDs, and capabilities, such as setuid,
> +	  setgid, and capset.
> +
> +	  If unsure, say Y here.
> +
>  config SGETMASK_SYSCALL
>  	bool "sgetmask/ssetmask syscalls support" if EXPERT
>  	def_bool PARISC || MN10300 || BLACKFIN || M68K || PPC || MIPS || X86 || SPARC || CRIS || MICROBLAZE || SUPERH
> diff --git a/kernel/Makefile b/kernel/Makefile
> index a59481a..554d34e 100644
> --- a/kernel/Makefile
> +++ b/kernel/Makefile
> @@ -9,7 +9,9 @@ obj-y     = fork.o exec_domain.o panic.o \
>  	    extable.o params.o \
>  	    kthread.o sys_ni.o nsproxy.o \
>  	    notifier.o ksysfs.o cred.o reboot.o \
> -	    async.o range.o groups.o smpboot.o
> +	    async.o range.o smpboot.o
> +
> +obj-$(CONFIG_MULTIUSER) += groups.o
> 
>  ifdef CONFIG_FUNCTION_TRACER
>  # Do not trace debug files and internal ftrace files
> diff --git a/kernel/capability.c b/kernel/capability.c
> index 989f5bf..638b0b3 100644
> --- a/kernel/capability.c
> +++ b/kernel/capability.c
> @@ -35,6 +35,7 @@ static int __init file_caps_disable(char *str)
>  }
>  __setup("no_file_caps", file_caps_disable);
> 
> +#ifdef CONFIG_MULTIUSER
>  /*
>   * More recent versions of libcap are available from:
>   *
> @@ -386,6 +387,24 @@ bool ns_capable(struct user_namespace *ns, int cap)
>  }
>  EXPORT_SYMBOL(ns_capable);
> 
> +
> +/**
> + * capable - Determine if the current task has a superior capability in effect
> + * @cap: The capability to be tested for
> + *
> + * Return true if the current task has the given superior capability currently
> + * available for use, false if not.
> + *
> + * This sets PF_SUPERPRIV on the task if the capability is available on the
> + * assumption that it's about to be used.
> + */
> +bool capable(int cap)
> +{
> +	return ns_capable(&init_user_ns, cap);
> +}
> +EXPORT_SYMBOL(capable);
> +#endif /* CONFIG_MULTIUSER */
> +
>  /**
>   * file_ns_capable - Determine if the file's opener had a capability in effect
>   * @file:  The file we want to check
> @@ -412,22 +431,6 @@ bool file_ns_capable(const struct file *file, struct user_namespace *ns,
>  EXPORT_SYMBOL(file_ns_capable);
> 
>  /**
> - * capable - Determine if the current task has a superior capability in effect
> - * @cap: The capability to be tested for
> - *
> - * Return true if the current task has the given superior capability currently
> - * available for use, false if not.
> - *
> - * This sets PF_SUPERPRIV on the task if the capability is available on the
> - * assumption that it's about to be used.
> - */
> -bool capable(int cap)
> -{
> -	return ns_capable(&init_user_ns, cap);
> -}
> -EXPORT_SYMBOL(capable);
> -
> -/**

OK, I'll bite...  Why are we moving capable()?

>   * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped
>   * @inode: The inode in question
>   * @cap: The capability in question
> diff --git a/kernel/cred.c b/kernel/cred.c
> index e0573a4..ec1c076 100644
> --- a/kernel/cred.c
> +++ b/kernel/cred.c
> @@ -29,6 +29,9 @@
> 
>  static struct kmem_cache *cred_jar;
> 
> +/* init to 2 - one for init_task, one to ensure it is never freed */
> +struct group_info init_groups = { .usage = ATOMIC_INIT(2) };
> +
>  /*
>   * The initial credentials for the initial task
>   */
> diff --git a/kernel/groups.c b/kernel/groups.c
> index 664411f..74d431d 100644
> --- a/kernel/groups.c
> +++ b/kernel/groups.c
> @@ -9,9 +9,6 @@
>  #include <linux/user_namespace.h>
>  #include <asm/uaccess.h>
> 
> -/* init to 2 - one for init_task, one to ensure it is never freed */
> -struct group_info init_groups = { .usage = ATOMIC_INIT(2) };
> -
>  struct group_info *groups_alloc(int gidsetsize)
>  {
>  	struct group_info *group_info;
> diff --git a/kernel/sys.c b/kernel/sys.c
> index ea9c881..3094e0f 100644
> --- a/kernel/sys.c
> +++ b/kernel/sys.c
> @@ -319,6 +319,7 @@ out_unlock:
>   * SMP: There are not races, the GIDs are checked only by filesystem
>   *      operations (as far as semantic preservation is concerned).
>   */
> +#ifdef CONFIG_MULTIUSER
>  SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid)
>  {
>  	struct user_namespace *ns = current_user_ns();
> @@ -809,6 +810,7 @@ change_okay:
>  	commit_creds(new);
>  	return old_fsgid;
>  }
> +#endif /* CONFIG_MULTIUSER */
> 
>  /**
>   * sys_getpid - return the thread group id of the current process
> diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
> index 5adcb0a..7995ef5 100644
> --- a/kernel/sys_ni.c
> +++ b/kernel/sys_ni.c
> @@ -159,6 +159,20 @@ cond_syscall(sys_uselib);
>  cond_syscall(sys_fadvise64);
>  cond_syscall(sys_fadvise64_64);
>  cond_syscall(sys_madvise);
> +cond_syscall(sys_setuid);
> +cond_syscall(sys_setregid);
> +cond_syscall(sys_setgid);
> +cond_syscall(sys_setreuid);
> +cond_syscall(sys_setresuid);
> +cond_syscall(sys_getresuid);
> +cond_syscall(sys_setresgid);
> +cond_syscall(sys_getresgid);
> +cond_syscall(sys_setgroups);
> +cond_syscall(sys_getgroups);
> +cond_syscall(sys_setfsuid);
> +cond_syscall(sys_setfsgid);
> +cond_syscall(sys_capget);
> +cond_syscall(sys_capset);
> 
>  /* arch-specific weak syscall entries */
>  cond_syscall(sys_pciconfig_read);
> diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
> index fb78117..9068e72 100644
> --- a/net/sunrpc/Kconfig
> +++ b/net/sunrpc/Kconfig
> @@ -1,9 +1,11 @@
>  config SUNRPC
>  	tristate
> +	depends on MULTIUSER
> 
>  config SUNRPC_GSS
>  	tristate
>  	select OID_REGISTRY
> +	depends on MULTIUSER
> 
>  config SUNRPC_BACKCHANNEL
>  	bool
> diff --git a/security/Kconfig b/security/Kconfig
> index beb86b5..bf4ec46 100644
> --- a/security/Kconfig
> +++ b/security/Kconfig
> @@ -21,6 +21,7 @@ config SECURITY_DMESG_RESTRICT
>  config SECURITY
>  	bool "Enable different security models"
>  	depends on SYSFS
> +	depends on MULTIUSER
>  	help
>  	  This allows you to choose different security modules to be
>  	  configured into your kernel.
> -- 
> 1.7.10.4

------------------------------------------------------------------------

nfs: Make NFS_FS depend on MULTIUSER

Building with CONFIG_MULTIUSER=n results in the following Kconfig
warnings:

warning: (NFS_FS) selects SUNRPC which has unmet direct dependencies (NETWORK_FILESYSTEMS && MULTIUSER)
warning: (NFS_V4 && NFSD_V4 && RPCSEC_GSS_KRB5) selects SUNRPC_GSS which has unmet direct dependencies (NETWORK_FILESYSTEMS && MULTIUSER)
warning: (NFS_FS) selects SUNRPC which has unmet direct dependencies (NETWORK_FILESYSTEMS && MULTIUSER)
warning: (NFS_V4 && NFSD_V4 && RPCSEC_GSS_KRB5) selects SUNRPC_GSS which has unmet direct dependencies (NETWORK_FILESYSTEMS && MULTIUSER)

This patch makes NFS_FS depend on MULTIUSER, eliminating these warnings.

Signed-off-by: Paul E. McKenney <paulmck@...ux.vnet.ibm.com>

diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 3dece03..07a902d 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -1,6 +1,6 @@
 config NFS_FS
 	tristate "NFS client support"
-	depends on INET && FILE_LOCKING
+	depends on INET && FILE_LOCKING && MULTIUSER
 	select LOCKD
 	select SUNRPC
 	select NFS_ACL_SUPPORT if NFS_V3_ACL

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ