[PATCH 2/3] cifs.upcall: namespace-aware key authority

Enzo Matsumiya <[email protected]>
Newsgroups org.kernel.vger.linux-cifs
Message-ID <[email protected]>
spnego key is allocated before switching namespaces (i.e. as root/host
credentials), but instantiation is done only later.

If we have successfully switched user namespaces, key instantiation
returns EPERM because credentials have changed.

Call keyctl_assume_authority() after switching NS/UID/GID so key is
instantiated with correct creds.

Signed-off-by: Enzo Matsumiya <[email protected]>
---
 cifs.upcall.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/cifs.upcall.c b/cifs.upcall.c
index 8a207544cf48..3f56c69cae28 100644
--- a/cifs.upcall.c
+++ b/cifs.upcall.c
@@ -1539,6 +1539,7 @@ int main(const int argc, char *const argv[])
 	krb5_ccache ccache = NULL;
 	unsigned expire_time = DNS_RESOLVER_DEFAULT_TIMEOUT;
 	const char *key_descr = NULL;
+	bool same_ns = true;
 
 	hostbuf[0] = '\0';
 
@@ -1688,6 +1689,7 @@ int main(const int argc, char *const argv[])
 	if (arg->upcall_target == UPTARGET_APP || arg->upcall_target == UPTARGET_UNSPECIFIED) {
 		syslog(LOG_INFO, "upcall_target=app, switching namespaces to application thread");
 		arg->upcall_target = UPTARGET_APP;
+		same_ns = in_same_user_ns(getpid(), arg->pid);
 		rc = switch_to_process_ns(arg->pid);
 		if (rc == -1) {
 			syslog(LOG_ERR, "unable to switch to process namespace: %s", strerror(errno));
@@ -1756,6 +1758,27 @@ int main(const int argc, char *const argv[])
 	if (rc)
 		goto out;
 
+	/*
+	 * Keyring keys' credentials are per user NS.  If we switched user namespaces, we need to
+	 * re-acquire authority (with correct UID/GID) over it so we're able to instantiate it
+	 * later (in setup_key()).
+	 */
+	if (!same_ns) {
+		errno = 0;
+		rc = keyctl_assume_authority(key);
+
+		/*
+		 * EINPROGRESS and ENOENT are non-fatal in most cases.
+		 * keyctl_instantiate() (in setup_key()) will fail if something was really
+		 * unexpected.
+		 */
+		if (rc < 0 && errno != EINPROGRESS && errno != ENOENT) {
+			syslog(LOG_ERR, "keyctl_assume_authority: %s", strerror(errno));
+			rc = 1;
+			goto out;
+		}
+	}
+
 	rc = krb5_init_context(&context);
 	if (rc) {
 		syslog(LOG_ERR, "unable to init krb5 context: %ld", rc);
-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.