All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
To: Stefan Metzmacher <metze@samba.org>,
	Namjae Jeon <namjae.jeon@samsung.com>
Cc: 'CIFS' <linux-cifs@vger.kernel.org>,
	'Steve French' <smfrench@gmail.com>,
	'samba-technical' <samba-technical@lists.samba.org>,
	'Hyunchul Lee' <hyc.lee@gmail.com>,
	Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Subject: Re: updated ksmbd (cifsd)
Date: Thu, 17 Dec 2020 12:29:02 +0900	[thread overview]
Message-ID: <X9rQfoW3BhOsX1ZX@jagdpanzerIV.localdomain> (raw)
In-Reply-To: <X9mLUOxGI8QM/tgV@jagdpanzerIV.localdomain>

On (20/12/16 13:21), Sergey Senozhatsky wrote:
> So SMB_SERVER_CHECK_CAP_NET_ADMIN enforces the "user-space must
> be a privileged process" policy. Even CAP_NET_ADMIN is too huge,
> not to mention that _probably_ this CAP requirement means that
> people will just "sudo cifsd". One way or another a malformed
> RPC request can do quite a bit of damage to the system, because
> user-space runs with the CAPs it doesn't really need.
> 
> It would be better to enforce a different policy, IMHO.
> Something like:
> 
> 	groupadd ... CIFSD_GROUP
> 	useradd -g CIFSD_GID -p CIFSD_PASSWORD CIFSD_LOGIN
> 	chmod 0700 smb.conf and password db
> 	chown CIFSD_LOGIN:CIFSD_GROUP smb.conf and password db

Just a sketch. Completely untested (wasn't even compile tested).
Merely an idea.

This removes the requirement for user-space to run as a privileged
process. Because "let's grant some random user-space daemon
administrative privileges" most likely doesn't improve security
of the system.

So the idea is to provide CIFSD administrator UID and GID during
kcifsd modprobe and then in IPC handlers check if the app issuing
a netlink syscall has the same UID and GID as the CIFSD administrator
or not.

This untested, sorry. Just checking the idea.

---

diff --git a/fs/cifsd/Kconfig b/fs/cifsd/Kconfig
index e12616cf8477..9f221a37223d 100644
--- a/fs/cifsd/Kconfig
+++ b/fs/cifsd/Kconfig
@@ -50,14 +50,6 @@ config SMB_SERVER_SMBDIRECT
 	  SMB Direct allows transferring SMB packets over RDMA. If unsure,
 	  say N.
 
-config SMB_SERVER_CHECK_CAP_NET_ADMIN
-	bool "Enable check network administration capability"
-	depends on SMB_SERVER
-	default n
-
-	help
-	  Prevent unprivileged processes to start the cifsd kernel server.
-
 config SMB_SERVER_KERBEROS5
 	bool "Support for Kerberos 5"
 	depends on SMB_SERVER
diff --git a/fs/cifsd/server.c b/fs/cifsd/server.c
index b9e114f8a5d2..dbbdb3503b0d 100644
--- a/fs/cifsd/server.c
+++ b/fs/cifsd/server.c
@@ -25,6 +25,7 @@
 
 int ksmbd_debug_types;
 
+static int admin_uid = -1, admin_gid = -1;
 struct ksmbd_server_config server_conf;
 
 enum SERVER_CTRL_TYPE {
@@ -335,6 +336,26 @@ static void server_conf_free(void)
 	}
 }
 
+static int server_admin_cred_init(void)
+{
+	if (admin_uid == -1 || admin_gid == -1)
+		return 0;
+
+	server_conf.admin_cred = kmalloc(sizeof(struct admin_cred), GFP_KERNEL);
+	if (!server_conf.admin_cred)
+		return -ENOMEM;
+
+	server_conf.admin_cred.uid = make_kuid(&init_user_ns, admin_uid);
+	server_conf.admin_cred.gid = make_kgid(&init_user_ns, admin_gid);
+	if (!(uid_validserver_conf.admin_cred.uid() &&
+	      gid_valid(server_conf.admin_cred.gid))) {
+		kfree(server_conf.admin_cred);
+		server_conf.admin_cred = NULL;
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int server_conf_init(void)
 {
 	WRITE_ONCE(server_conf.state, SERVER_STATE_STARTING_UP);
@@ -343,10 +364,9 @@ static int server_conf_init(void)
 	server_conf.max_protocol = ksmbd_max_protocol();
 	server_conf.auth_mechs = KSMBD_AUTH_NTLMSSP;
 #ifdef CONFIG_SMB_SERVER_KERBEROS5
-	server_conf.auth_mechs |= KSMBD_AUTH_KRB5 |
-				KSMBD_AUTH_MSKRB5;
+	server_conf.auth_mechs |= KSMBD_AUTH_KRB5 | KSMBD_AUTH_MSKRB5;
 #endif
-	return 0;
+	return server_admin_cred_init();
 }
 
 static void server_ctrl_handle_init(struct server_ctrl_struct *ctrl)
@@ -418,6 +438,21 @@ int server_queue_ctrl_reset_work(void)
 	return __queue_ctrl_work(SERVER_CTRL_TYPE_RESET);
 }
 
+int server_validate_admin_cred(void)
+{
+	if (admin_uid == -1 || admin_gid == -1)
+		return 0;
+
+	/* We couldn't init server admin UID/GID */
+	if (!server_conf.admin_cred)
+		return -EINVAL;
+
+	if (uid_eq(task_uid(current), server_conf.admin_cred.uid) &&
+	    gid_eq(task_gid(current), server_conf.admin_cred.gid))
+		return 0;
+	return -EINVAL;
+}
+
 static ssize_t stats_show(struct class *class,
 			  struct class_attribute *attr,
 			  char *buf)
@@ -614,6 +649,11 @@ static void __exit ksmbd_server_exit(void)
 	ksmbd_release_inode_hash();
 }
 
+module_param(admin_uid, int, 0);
+MODULE_PARM_DESC(admin_uid, "ksmb administrator user id");
+module_param(admin_gid, int, 0);
+MODULE_PARM_DESC(admin_gid, "ksmb administrator group id");
+
 MODULE_AUTHOR("Namjae Jeon <linkinjeon@kernel.org>");
 MODULE_VERSION(KSMBD_VERSION);
 MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER");
diff --git a/fs/cifsd/server.h b/fs/cifsd/server.h
index 7b2f6318fcff..ed0249061470 100644
--- a/fs/cifsd/server.h
+++ b/fs/cifsd/server.h
@@ -19,6 +19,11 @@
 
 extern int ksmbd_debugging;
 
+struct admin_cred {
+	kuid_t			uid;
+	kgid_t			gid;
+};
+
 struct ksmbd_server_config {
 	unsigned int		flags;
 	unsigned int		state;
@@ -34,6 +39,7 @@ struct ksmbd_server_config {
 	struct smb_sid		domain_sid;
 	unsigned int		auth_mechs;
 
+	struct admin_cred	*admin_cred;
 	char			*conf[SERVER_CONF_WORK_GROUP + 1];
 };
 
@@ -57,6 +63,7 @@ static inline int ksmbd_server_configurable(void)
 	return READ_ONCE(server_conf.state) < SERVER_STATE_RESETTING;
 }
 
+int server_verify_admin_cred(void);
 int server_queue_ctrl_init_work(void);
 int server_queue_ctrl_reset_work(void);
 #endif /* __SERVER_H__ */
diff --git a/fs/cifsd/transport_ipc.c b/fs/cifsd/transport_ipc.c
index 5f24a1ed5c34..b2a42f6ce6e3 100644
--- a/fs/cifsd/transport_ipc.c
+++ b/fs/cifsd/transport_ipc.c
@@ -345,10 +345,8 @@ static int handle_startup_event(struct sk_buff *skb, struct genl_info *info)
 {
 	int ret = 0;
 
-#ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
-	if (!netlink_capable(skb, CAP_NET_ADMIN))
+	if (server_validate_admin_cred())
 		return -EPERM;
-#endif
 
 	if (!ksmbd_ipc_validate_version(info))
 		return -EINVAL;
@@ -401,10 +399,8 @@ static int handle_generic_event(struct sk_buff *skb, struct genl_info *info)
 	int sz;
 	int type = info->genlhdr->cmd;
 
-#ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
-	if (!netlink_capable(skb, CAP_NET_ADMIN))
+	if (server_validate_admin_cred())
 		return -EPERM;
-#endif
 
 	if (type >= KSMBD_EVENT_MAX) {
 		WARN_ON(1);

  reply	other threads:[~2020-12-17  3:29 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-14  1:20 updated ksmbd (cifsd) Steve French
2020-12-14 12:46 ` Namjae Jeon
2020-12-15  2:28   ` Namjae Jeon
2020-12-14 17:45 ` Stefan Metzmacher
2020-12-14 18:48   ` Jeremy Allison
2020-12-15  2:29     ` Namjae Jeon
2020-12-15  4:13       ` Jeremy Allison
2020-12-15  2:28   ` Namjae Jeon
2020-12-15 14:29     ` Stefan Metzmacher
2020-12-16  3:24       ` Sergey Senozhatsky
2020-12-16  4:21         ` Sergey Senozhatsky
2020-12-17  3:29           ` Sergey Senozhatsky [this message]
2020-12-16  8:50       ` Namjae Jeon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=X9rQfoW3BhOsX1ZX@jagdpanzerIV.localdomain \
    --to=sergey.senozhatsky@gmail.com \
    --cc=hyc.lee@gmail.com \
    --cc=linux-cifs@vger.kernel.org \
    --cc=metze@samba.org \
    --cc=namjae.jeon@samsung.com \
    --cc=samba-technical@lists.samba.org \
    --cc=smfrench@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.