Skip to content

Commit db363b0

Browse files
ritbudhirajaSteve French
authored andcommitted
CIFS: New mount option for cifs.upcall namespace resolution
In the current implementation, the SMB filesystem on a mount point can trigger upcalls from the kernel to the userspace to enable certain functionalities like spnego, dns_resolution, amongst others. These upcalls usually either happen in the context of the mount or in the context of an application/user. The upcall handler for cifs, cifs.upcall already has existing code which switches the namespaces to the caller's namespace before handling the upcall. This behaviour is expected for scenarios like multiuser mounts, but might not cover all single user scenario with services such as Kubernetes, where the mount can happen from different locations such as on the host, from an app container, or a driver pod which does the mount on behalf of a different pod. This patch introduces a new mount option called upcall_target, to customise the upcall behaviour. upcall_target can take 'mount' and 'app' as possible values. This aids use cases like Kubernetes where the mount happens on behalf of the application in another container altogether. Having this new mount option allows the mount command to specify where the upcall should happen: 'mount' for resolving the upcall to the host namespace, and 'app' for resolving the upcall to the ns of the calling thread. This will enable both the scenarios where the Kerberos credentials can be found on the application namespace or the host namespace to which just the mount operation is "delegated". Reviewed-by: Shyam Prasad <[email protected]> Reviewed-by: Bharath S M <[email protected]> Reviewed-by: Ronnie Sahlberg <[email protected]> Signed-off-by: Ritvik Budhiraja <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 7a2158b commit db363b0

File tree

6 files changed

+117
-0
lines changed

6 files changed

+117
-0
lines changed

fs/smb/client/cifs_spnego.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ struct key_type cifs_spnego_key_type = {
8282
/* strlen of ";pid=0x" */
8383
#define PID_KEY_LEN 7
8484

85+
/* strlen of ";upcall_target=" */
86+
#define UPCALL_TARGET_KEY_LEN 15
87+
8588
/* get a key struct with a SPNEGO security blob, suitable for session setup */
8689
struct key *
8790
cifs_get_spnego_key(struct cifs_ses *sesInfo,
@@ -108,6 +111,11 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo,
108111
if (sesInfo->user_name)
109112
desc_len += USER_KEY_LEN + strlen(sesInfo->user_name);
110113

114+
if (sesInfo->upcall_target == UPTARGET_MOUNT)
115+
desc_len += UPCALL_TARGET_KEY_LEN + 5; // strlen("mount")
116+
else
117+
desc_len += UPCALL_TARGET_KEY_LEN + 3; // strlen("app")
118+
111119
spnego_key = ERR_PTR(-ENOMEM);
112120
description = kzalloc(desc_len, GFP_KERNEL);
113121
if (description == NULL)
@@ -156,6 +164,14 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo,
156164
dp = description + strlen(description);
157165
sprintf(dp, ";pid=0x%x", current->pid);
158166

167+
if (sesInfo->upcall_target == UPTARGET_MOUNT) {
168+
dp = description + strlen(description);
169+
sprintf(dp, ";upcall_target=mount");
170+
} else {
171+
dp = description + strlen(description);
172+
sprintf(dp, ";upcall_target=app");
173+
}
174+
159175
cifs_dbg(FYI, "key description = %s\n", description);
160176
saved_cred = override_creds(spnego_cred);
161177
spnego_key = request_key(&cifs_spnego_key_type, description, "");

fs/smb/client/cifsfs.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,30 @@ static int cifs_show_devname(struct seq_file *m, struct dentry *root)
546546
return 0;
547547
}
548548

549+
static void
550+
cifs_show_upcall_target(struct seq_file *s, struct cifs_sb_info *cifs_sb)
551+
{
552+
if (cifs_sb->ctx->upcall_target == UPTARGET_UNSPECIFIED) {
553+
seq_puts(s, ",upcall_target=app");
554+
return;
555+
}
556+
557+
seq_puts(s, ",upcall_target=");
558+
559+
switch (cifs_sb->ctx->upcall_target) {
560+
case UPTARGET_APP:
561+
seq_puts(s, "app");
562+
break;
563+
case UPTARGET_MOUNT:
564+
seq_puts(s, "mount");
565+
break;
566+
default:
567+
/* shouldn't ever happen */
568+
seq_puts(s, "unknown");
569+
break;
570+
}
571+
}
572+
549573
/*
550574
* cifs_show_options() is for displaying mount options in /proc/mounts.
551575
* Not all settable options are displayed but most of the important
@@ -562,6 +586,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
562586
seq_show_option(s, "vers", tcon->ses->server->vals->version_string);
563587
cifs_show_security(s, tcon->ses);
564588
cifs_show_cache_flavor(s, cifs_sb);
589+
cifs_show_upcall_target(s, cifs_sb);
565590

566591
if (tcon->no_lease)
567592
seq_puts(s, ",nolease");

fs/smb/client/cifsglob.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ enum securityEnum {
153153
Kerberos, /* Kerberos via SPNEGO */
154154
};
155155

156+
enum upcall_target_enum {
157+
UPTARGET_UNSPECIFIED, /* not specified, defaults to app */
158+
UPTARGET_MOUNT, /* upcall to the mount namespace */
159+
UPTARGET_APP, /* upcall to the application namespace which did the mount */
160+
};
161+
156162
enum cifs_reparse_type {
157163
CIFS_REPARSE_TYPE_NFS,
158164
CIFS_REPARSE_TYPE_WSL,
@@ -1084,6 +1090,7 @@ struct cifs_ses {
10841090
struct session_key auth_key;
10851091
struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
10861092
enum securityEnum sectype; /* what security flavor was specified? */
1093+
enum upcall_target_enum upcall_target; /* what upcall target was specified? */
10871094
bool sign; /* is signing required? */
10881095
bool domainAuto:1;
10891096
bool expired_pwd; /* track if access denied or expired pwd so can know if need to update */

fs/smb/client/connect.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2339,6 +2339,26 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
23392339

23402340
ses->sectype = ctx->sectype;
23412341
ses->sign = ctx->sign;
2342+
2343+
/*
2344+
*Explicitly marking upcall_target mount option for easier handling
2345+
* by cifs_spnego.c and eventually cifs.upcall.c
2346+
*/
2347+
2348+
switch (ctx->upcall_target) {
2349+
case UPTARGET_UNSPECIFIED: /* default to app */
2350+
case UPTARGET_APP:
2351+
ses->upcall_target = UPTARGET_APP;
2352+
break;
2353+
case UPTARGET_MOUNT:
2354+
ses->upcall_target = UPTARGET_MOUNT;
2355+
break;
2356+
default:
2357+
// should never happen
2358+
ses->upcall_target = UPTARGET_APP;
2359+
break;
2360+
}
2361+
23422362
ses->local_nls = load_nls(ctx->local_nls->charset);
23432363

23442364
/* add server as first channel */

fs/smb/client/fs_context.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ static const match_table_t cifs_secflavor_tokens = {
6767
{ Opt_sec_err, NULL }
6868
};
6969

70+
static const match_table_t cifs_upcall_target = {
71+
{ Opt_upcall_target_mount, "mount" },
72+
{ Opt_upcall_target_application, "app" },
73+
{ Opt_upcall_target_err, NULL }
74+
};
75+
7076
const struct fs_parameter_spec smb3_fs_parameters[] = {
7177
/* Mount options that take no arguments */
7278
fsparam_flag_no("user_xattr", Opt_user_xattr),
@@ -178,6 +184,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
178184
fsparam_string("sec", Opt_sec),
179185
fsparam_string("cache", Opt_cache),
180186
fsparam_string("reparse", Opt_reparse),
187+
fsparam_string("upcall_target", Opt_upcalltarget),
181188

182189
/* Arguments that should be ignored */
183190
fsparam_flag("guest", Opt_ignore),
@@ -248,6 +255,29 @@ cifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_c
248255
return 0;
249256
}
250257

258+
static int
259+
cifs_parse_upcall_target(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
260+
{
261+
substring_t args[MAX_OPT_ARGS];
262+
263+
ctx->upcall_target = UPTARGET_UNSPECIFIED;
264+
265+
switch (match_token(value, cifs_upcall_target, args)) {
266+
case Opt_upcall_target_mount:
267+
ctx->upcall_target = UPTARGET_MOUNT;
268+
break;
269+
case Opt_upcall_target_application:
270+
ctx->upcall_target = UPTARGET_APP;
271+
break;
272+
273+
default:
274+
cifs_errorf(fc, "bad upcall target: %s\n", value);
275+
return 1;
276+
}
277+
278+
return 0;
279+
}
280+
251281
static const match_table_t cifs_cacheflavor_tokens = {
252282
{ Opt_cache_loose, "loose" },
253283
{ Opt_cache_strict, "strict" },
@@ -1450,6 +1480,10 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
14501480
if (cifs_parse_security_flavors(fc, param->string, ctx) != 0)
14511481
goto cifs_parse_mount_err;
14521482
break;
1483+
case Opt_upcalltarget:
1484+
if (cifs_parse_upcall_target(fc, param->string, ctx) != 0)
1485+
goto cifs_parse_mount_err;
1486+
break;
14531487
case Opt_cache:
14541488
if (cifs_parse_cache_flavor(fc, param->string, ctx) != 0)
14551489
goto cifs_parse_mount_err;
@@ -1627,6 +1661,11 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
16271661
}
16281662
/* case Opt_ignore: - is ignored as expected ... */
16291663

1664+
if (ctx->multiuser && ctx->upcall_target == UPTARGET_MOUNT) {
1665+
cifs_errorf(fc, "multiuser mount option not supported with upcalltarget set as 'mount'\n");
1666+
goto cifs_parse_mount_err;
1667+
}
1668+
16301669
return 0;
16311670

16321671
cifs_parse_mount_err:

fs/smb/client/fs_context.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ enum cifs_sec_param {
6161
Opt_sec_err
6262
};
6363

64+
enum cifs_upcall_target_param {
65+
Opt_upcall_target_mount,
66+
Opt_upcall_target_application,
67+
Opt_upcall_target_err
68+
};
69+
6470
enum cifs_param {
6571
/* Mount options that take no arguments */
6672
Opt_user_xattr,
@@ -114,6 +120,8 @@ enum cifs_param {
114120
Opt_multichannel,
115121
Opt_compress,
116122
Opt_witness,
123+
Opt_is_upcall_target_mount,
124+
Opt_is_upcall_target_application,
117125

118126
/* Mount options which take numeric value */
119127
Opt_backupuid,
@@ -157,6 +165,7 @@ enum cifs_param {
157165
Opt_sec,
158166
Opt_cache,
159167
Opt_reparse,
168+
Opt_upcalltarget,
160169

161170
/* Mount options to be ignored */
162171
Opt_ignore,
@@ -198,6 +207,7 @@ struct smb3_fs_context {
198207
umode_t file_mode;
199208
umode_t dir_mode;
200209
enum securityEnum sectype; /* sectype requested via mnt opts */
210+
enum upcall_target_enum upcall_target; /* where to upcall for mount */
201211
bool sign; /* was signing requested via mnt opts? */
202212
bool ignore_signature:1;
203213
bool retry:1;

0 commit comments

Comments
 (0)