Skip to content

Commit 6b2d1fb

Browse files
ritbudhirajagregkh
authored andcommitted
CIFS: New mount option for cifs.upcall namespace resolution
commit db363b0 upstream. 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]> Cc: Salvatore Bonaccorso <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 23dc14c commit 6b2d1fb

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)
@@ -158,6 +166,14 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo,
158166
dp = description + strlen(description);
159167
sprintf(dp, ";pid=0x%x", current->pid);
160168

169+
if (sesInfo->upcall_target == UPTARGET_MOUNT) {
170+
dp = description + strlen(description);
171+
sprintf(dp, ";upcall_target=mount");
172+
} else {
173+
dp = description + strlen(description);
174+
sprintf(dp, ";upcall_target=app");
175+
}
176+
161177
cifs_dbg(FYI, "key description = %s\n", description);
162178
saved_cred = override_creds(spnego_cred);
163179
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
@@ -547,6 +547,30 @@ static int cifs_show_devname(struct seq_file *m, struct dentry *root)
547547
return 0;
548548
}
549549

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

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

fs/smb/client/cifsglob.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ enum securityEnum {
154154
IAKerb, /* Kerberos proxy */
155155
};
156156

157+
enum upcall_target_enum {
158+
UPTARGET_UNSPECIFIED, /* not specified, defaults to app */
159+
UPTARGET_MOUNT, /* upcall to the mount namespace */
160+
UPTARGET_APP, /* upcall to the application namespace which did the mount */
161+
};
162+
157163
enum cifs_reparse_type {
158164
CIFS_REPARSE_TYPE_NFS,
159165
CIFS_REPARSE_TYPE_WSL,
@@ -1085,6 +1091,7 @@ struct cifs_ses {
10851091
struct session_key auth_key;
10861092
struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
10871093
enum securityEnum sectype; /* what security flavor was specified? */
1094+
enum upcall_target_enum upcall_target; /* what upcall target was specified? */
10881095
bool sign; /* is signing required? */
10891096
bool domainAuto:1;
10901097
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
@@ -2381,6 +2381,26 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
23812381

23822382
ses->sectype = ctx->sectype;
23832383
ses->sign = ctx->sign;
2384+
2385+
/*
2386+
*Explicitly marking upcall_target mount option for easier handling
2387+
* by cifs_spnego.c and eventually cifs.upcall.c
2388+
*/
2389+
2390+
switch (ctx->upcall_target) {
2391+
case UPTARGET_UNSPECIFIED: /* default to app */
2392+
case UPTARGET_APP:
2393+
ses->upcall_target = UPTARGET_APP;
2394+
break;
2395+
case UPTARGET_MOUNT:
2396+
ses->upcall_target = UPTARGET_MOUNT;
2397+
break;
2398+
default:
2399+
// should never happen
2400+
ses->upcall_target = UPTARGET_APP;
2401+
break;
2402+
}
2403+
23842404
ses->local_nls = load_nls(ctx->local_nls->charset);
23852405

23862406
/* 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),
@@ -179,6 +185,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
179185
fsparam_string("sec", Opt_sec),
180186
fsparam_string("cache", Opt_cache),
181187
fsparam_string("reparse", Opt_reparse),
188+
fsparam_string("upcall_target", Opt_upcalltarget),
182189

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

259+
static int
260+
cifs_parse_upcall_target(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
261+
{
262+
substring_t args[MAX_OPT_ARGS];
263+
264+
ctx->upcall_target = UPTARGET_UNSPECIFIED;
265+
266+
switch (match_token(value, cifs_upcall_target, args)) {
267+
case Opt_upcall_target_mount:
268+
ctx->upcall_target = UPTARGET_MOUNT;
269+
break;
270+
case Opt_upcall_target_application:
271+
ctx->upcall_target = UPTARGET_APP;
272+
break;
273+
274+
default:
275+
cifs_errorf(fc, "bad upcall target: %s\n", value);
276+
return 1;
277+
}
278+
279+
return 0;
280+
}
281+
252282
static const match_table_t cifs_cacheflavor_tokens = {
253283
{ Opt_cache_loose, "loose" },
254284
{ Opt_cache_strict, "strict" },
@@ -1526,6 +1556,10 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
15261556
if (cifs_parse_security_flavors(fc, param->string, ctx) != 0)
15271557
goto cifs_parse_mount_err;
15281558
break;
1559+
case Opt_upcalltarget:
1560+
if (cifs_parse_upcall_target(fc, param->string, ctx) != 0)
1561+
goto cifs_parse_mount_err;
1562+
break;
15291563
case Opt_cache:
15301564
if (cifs_parse_cache_flavor(fc, param->string, ctx) != 0)
15311565
goto cifs_parse_mount_err;
@@ -1703,6 +1737,11 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
17031737
}
17041738
/* case Opt_ignore: - is ignored as expected ... */
17051739

1740+
if (ctx->multiuser && ctx->upcall_target == UPTARGET_MOUNT) {
1741+
cifs_errorf(fc, "multiuser mount option not supported with upcalltarget set as 'mount'\n");
1742+
goto cifs_parse_mount_err;
1743+
}
1744+
17061745
return 0;
17071746

17081747
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)