|
40 | 40 | #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
|
41 | 41 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
|
42 | 42 |
|
43 |
| -static void expkey_put(struct kref *ref) |
| 43 | +static void expkey_put_work(struct work_struct *work) |
44 | 44 | {
|
45 |
| - struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); |
| 45 | + struct svc_expkey *key = |
| 46 | + container_of(to_rcu_work(work), struct svc_expkey, ek_rcu_work); |
46 | 47 |
|
47 | 48 | if (test_bit(CACHE_VALID, &key->h.flags) &&
|
48 | 49 | !test_bit(CACHE_NEGATIVE, &key->h.flags))
|
49 | 50 | path_put(&key->ek_path);
|
50 | 51 | auth_domain_put(key->ek_client);
|
51 |
| - kfree_rcu(key, ek_rcu); |
| 52 | + kfree(key); |
| 53 | +} |
| 54 | + |
| 55 | +static void expkey_put(struct kref *ref) |
| 56 | +{ |
| 57 | + struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); |
| 58 | + |
| 59 | + INIT_RCU_WORK(&key->ek_rcu_work, expkey_put_work); |
| 60 | + queue_rcu_work(system_wq, &key->ek_rcu_work); |
52 | 61 | }
|
53 | 62 |
|
54 | 63 | static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
|
@@ -355,16 +364,26 @@ static void export_stats_destroy(struct export_stats *stats)
|
355 | 364 | EXP_STATS_COUNTERS_NUM);
|
356 | 365 | }
|
357 | 366 |
|
358 |
| -static void svc_export_put(struct kref *ref) |
| 367 | +static void svc_export_put_work(struct work_struct *work) |
359 | 368 | {
|
360 |
| - struct svc_export *exp = container_of(ref, struct svc_export, h.ref); |
| 369 | + struct svc_export *exp = |
| 370 | + container_of(to_rcu_work(work), struct svc_export, ex_rcu_work); |
| 371 | + |
361 | 372 | path_put(&exp->ex_path);
|
362 | 373 | auth_domain_put(exp->ex_client);
|
363 | 374 | nfsd4_fslocs_free(&exp->ex_fslocs);
|
364 | 375 | export_stats_destroy(exp->ex_stats);
|
365 | 376 | kfree(exp->ex_stats);
|
366 | 377 | kfree(exp->ex_uuid);
|
367 |
| - kfree_rcu(exp, ex_rcu); |
| 378 | + kfree(exp); |
| 379 | +} |
| 380 | + |
| 381 | +static void svc_export_put(struct kref *ref) |
| 382 | +{ |
| 383 | + struct svc_export *exp = container_of(ref, struct svc_export, h.ref); |
| 384 | + |
| 385 | + INIT_RCU_WORK(&exp->ex_rcu_work, svc_export_put_work); |
| 386 | + queue_rcu_work(system_wq, &exp->ex_rcu_work); |
368 | 387 | }
|
369 | 388 |
|
370 | 389 | static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)
|
@@ -1078,12 +1097,14 @@ static struct svc_export *exp_find(struct cache_detail *cd,
|
1078 | 1097 | * check_nfsd_access - check if access to export is allowed.
|
1079 | 1098 | * @exp: svc_export that is being accessed.
|
1080 | 1099 | * @rqstp: svc_rqst attempting to access @exp (will be NULL for LOCALIO).
|
| 1100 | + * @may_bypass_gss: reduce strictness of authorization check |
1081 | 1101 | *
|
1082 | 1102 | * Return values:
|
1083 | 1103 | * %nfs_ok if access is granted, or
|
1084 | 1104 | * %nfserr_wrongsec if access is denied
|
1085 | 1105 | */
|
1086 |
| -__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) |
| 1106 | +__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp, |
| 1107 | + bool may_bypass_gss) |
1087 | 1108 | {
|
1088 | 1109 | struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors;
|
1089 | 1110 | struct svc_xprt *xprt;
|
@@ -1140,6 +1161,23 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
|
1140 | 1161 | if (nfsd4_spo_must_allow(rqstp))
|
1141 | 1162 | return nfs_ok;
|
1142 | 1163 |
|
| 1164 | + /* Some calls may be processed without authentication |
| 1165 | + * on GSS exports. For example NFS2/3 calls on root |
| 1166 | + * directory, see section 2.3.2 of rfc 2623. |
| 1167 | + * For "may_bypass_gss" check that export has really |
| 1168 | + * enabled some flavor with authentication (GSS or any |
| 1169 | + * other) and also check that the used auth flavor is |
| 1170 | + * without authentication (none or sys). |
| 1171 | + */ |
| 1172 | + if (may_bypass_gss && ( |
| 1173 | + rqstp->rq_cred.cr_flavor == RPC_AUTH_NULL || |
| 1174 | + rqstp->rq_cred.cr_flavor == RPC_AUTH_UNIX)) { |
| 1175 | + for (f = exp->ex_flavors; f < end; f++) { |
| 1176 | + if (f->pseudoflavor >= RPC_AUTH_DES) |
| 1177 | + return 0; |
| 1178 | + } |
| 1179 | + } |
| 1180 | + |
1143 | 1181 | denied:
|
1144 | 1182 | return nfserr_wrongsec;
|
1145 | 1183 | }
|
@@ -1406,9 +1444,12 @@ static int e_show(struct seq_file *m, void *p)
|
1406 | 1444 | return 0;
|
1407 | 1445 | }
|
1408 | 1446 |
|
1409 |
| - exp_get(exp); |
| 1447 | + if (!cache_get_rcu(&exp->h)) |
| 1448 | + return 0; |
| 1449 | + |
1410 | 1450 | if (cache_check(cd, &exp->h, NULL))
|
1411 | 1451 | return 0;
|
| 1452 | + |
1412 | 1453 | exp_put(exp);
|
1413 | 1454 | return svc_export_show(m, cd, cp);
|
1414 | 1455 | }
|
|
0 commit comments