1 From: Chunwei Chen <david.chen@osnexus.com>
2 Date: Tue, 18 Oct 2016 15:52:30 -0700
3 Subject: Fix crgetgroups out-of-bound and misc cred fix
5 init_groups has 0 nblocks, therefore calling the current crgetgroups with
6 init_groups would result in out-of-bound access. We fix this by returning NULL
9 Cap crgetngroups to NGROUPS_PER_BLOCK, since crgetgroups will only return
12 Also, remove all get_group_info. The cred already holds reference on the
13 group_info, and cred is not mutable. So there's no reason to hold extra
14 reference, if we hold cred.
16 Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
17 Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
20 module/spl/spl-cred.c | 31 ++++++++++++++++---------------
21 1 file changed, 16 insertions(+), 15 deletions(-)
23 diff --git a/module/spl/spl-cred.c b/module/spl/spl-cred.c
24 index a03f459..d046f95 100644
25 --- a/module/spl/spl-cred.c
26 +++ b/module/spl/spl-cred.c
27 @@ -62,19 +62,17 @@ cr_groups_search(const struct group_info *group_info, gid_t grp)
31 -/* Hold a reference on the credential and group info */
32 +/* Hold a reference on the credential */
36 (void)get_cred((const cred_t *)cr);
37 - (void)get_group_info(cr->group_info);
40 -/* Free a reference on the credential and group info */
41 +/* Free a reference on the credential */
45 - put_group_info(cr->group_info);
46 put_cred((const cred_t *)cr);
49 @@ -85,28 +83,32 @@ crgetngroups(const cred_t *cr)
50 struct group_info *gi;
53 - gi = get_group_info(cr->group_info);
54 + gi = cr->group_info;
59 + * crgetgroups will only returns gi->blocks[0], which contains only
60 + * the first NGROUPS_PER_BLOCK groups.
62 + if (rc > NGROUPS_PER_BLOCK) {
64 + rc = NGROUPS_PER_BLOCK;
70 * Return an array of supplemental gids. The returned address is safe
71 * to use as long as the caller has taken a reference with crhold().
72 - * The caller is responsible for releasing the reference with crfree().
75 crgetgroups(const cred_t *cr)
77 struct group_info *gi;
80 - gi = get_group_info(cr->group_info);
81 - gids = KGIDP_TO_SGIDP(gi->blocks[0]);
85 + gi = cr->group_info;
86 + if (gi->nblocks > 0)
87 + gids = KGIDP_TO_SGIDP(gi->blocks[0]);
91 @@ -117,9 +119,8 @@ groupmember(gid_t gid, const cred_t *cr)
92 struct group_info *gi;
95 - gi = get_group_info(cr->group_info);
96 + gi = cr->group_info;
97 rc = cr_groups_search(gi, SGID_TO_KGID(gid));