Skip to content

Commit fe0d629

Browse files
committed
Merge: SUNRPC: introduce cache_check_rcu to help check in rcu context
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/421 JIRA: https://issues.redhat.com/browse/RHEL-80508 CVE: CVE-2024-53216 Comment: CVE identifies a patch which is reverted in the same release in favor of a different fix. Four patches included in this MR fix the problem that the CVE in question described. Signed-off-by: Olga Kornievskaia <okorniev@redhat.com> Approved-by: Benjamin Coddington <bcodding@redhat.com> Approved-by: Scott Mayhew <smayhew@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Julio Faracco <jfaracco@redhat.com>
2 parents 0b6715e + 69b234c commit fe0d629

File tree

3 files changed

+46
-34
lines changed

3 files changed

+46
-34
lines changed

fs/nfsd/export.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -355,16 +355,25 @@ static void export_stats_destroy(struct export_stats *stats)
355355
EXP_STATS_COUNTERS_NUM);
356356
}
357357

358-
static void svc_export_put(struct kref *ref)
358+
static void svc_export_release(struct rcu_head *rcu_head)
359359
{
360-
struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
361-
path_put(&exp->ex_path);
362-
auth_domain_put(exp->ex_client);
360+
struct svc_export *exp = container_of(rcu_head, struct svc_export,
361+
ex_rcu);
362+
363363
nfsd4_fslocs_free(&exp->ex_fslocs);
364364
export_stats_destroy(exp->ex_stats);
365365
kfree(exp->ex_stats);
366366
kfree(exp->ex_uuid);
367-
kfree_rcu(exp, ex_rcu);
367+
kfree(exp);
368+
}
369+
370+
static void svc_export_put(struct kref *ref)
371+
{
372+
struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
373+
374+
path_put(&exp->ex_path);
375+
auth_domain_put(exp->ex_client);
376+
call_rcu(&exp->ex_rcu, svc_export_release);
368377
}
369378

370379
static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)
@@ -1431,13 +1440,9 @@ static int e_show(struct seq_file *m, void *p)
14311440
return 0;
14321441
}
14331442

1434-
if (!cache_get_rcu(&exp->h))
1435-
return 0;
1436-
1437-
if (cache_check(cd, &exp->h, NULL))
1443+
if (cache_check_rcu(cd, &exp->h, NULL))
14381444
return 0;
14391445

1440-
exp_put(exp);
14411446
return svc_export_show(m, cd, cp);
14421447
}
14431448

include/linux/sunrpc/cache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ static inline bool cache_is_expired(struct cache_detail *detail, struct cache_he
222222
return detail->flush_time >= h->last_refresh;
223223
}
224224

225+
extern int cache_check_rcu(struct cache_detail *detail,
226+
struct cache_head *h, struct cache_req *rqstp);
225227
extern int cache_check(struct cache_detail *detail,
226228
struct cache_head *h, struct cache_req *rqstp);
227229
extern void cache_flush(void);

net/sunrpc/cache.c

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -281,21 +281,7 @@ static int try_to_negate_entry(struct cache_detail *detail, struct cache_head *h
281281
return rv;
282282
}
283283

284-
/*
285-
* This is the generic cache management routine for all
286-
* the authentication caches.
287-
* It checks the currency of a cache item and will (later)
288-
* initiate an upcall to fill it if needed.
289-
*
290-
*
291-
* Returns 0 if the cache_head can be used, or cache_puts it and returns
292-
* -EAGAIN if upcall is pending and request has been queued
293-
* -ETIMEDOUT if upcall failed or request could not be queue or
294-
* upcall completed but item is still invalid (implying that
295-
* the cache item has been replaced with a newer one).
296-
* -ENOENT if cache entry was negative
297-
*/
298-
int cache_check(struct cache_detail *detail,
284+
int cache_check_rcu(struct cache_detail *detail,
299285
struct cache_head *h, struct cache_req *rqstp)
300286
{
301287
int rv;
@@ -336,6 +322,31 @@ int cache_check(struct cache_detail *detail,
336322
rv = -ETIMEDOUT;
337323
}
338324
}
325+
326+
return rv;
327+
}
328+
EXPORT_SYMBOL_GPL(cache_check_rcu);
329+
330+
/*
331+
* This is the generic cache management routine for all
332+
* the authentication caches.
333+
* It checks the currency of a cache item and will (later)
334+
* initiate an upcall to fill it if needed.
335+
*
336+
*
337+
* Returns 0 if the cache_head can be used, or cache_puts it and returns
338+
* -EAGAIN if upcall is pending and request has been queued
339+
* -ETIMEDOUT if upcall failed or request could not be queue or
340+
* upcall completed but item is still invalid (implying that
341+
* the cache item has been replaced with a newer one).
342+
* -ENOENT if cache entry was negative
343+
*/
344+
int cache_check(struct cache_detail *detail,
345+
struct cache_head *h, struct cache_req *rqstp)
346+
{
347+
int rv;
348+
349+
rv = cache_check_rcu(detail, h, rqstp);
339350
if (rv)
340351
cache_put(h, detail);
341352
return rv;
@@ -1427,17 +1438,11 @@ static int c_show(struct seq_file *m, void *p)
14271438
seq_printf(m, "# expiry=%lld refcnt=%d flags=%lx\n",
14281439
convert_to_wallclock(cp->expiry_time),
14291440
kref_read(&cp->ref), cp->flags);
1430-
if (!cache_get_rcu(cp))
1431-
return 0;
14321441

1433-
if (cache_check(cd, cp, NULL))
1434-
/* cache_check does a cache_put on failure */
1442+
if (cache_check_rcu(cd, cp, NULL))
1443+
seq_puts(m, "# ");
1444+
else if (cache_is_expired(cd, cp))
14351445
seq_puts(m, "# ");
1436-
else {
1437-
if (cache_is_expired(cd, cp))
1438-
seq_puts(m, "# ");
1439-
cache_put(cp, cd);
1440-
}
14411446

14421447
return cd->cache_show(m, cd, cp);
14431448
}

0 commit comments

Comments
 (0)