diff options
author | J. Bruce Fields <bfields@redhat.com> | 2013-08-21 10:32:52 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2013-09-06 11:45:56 -0400 |
commit | 778e512bb1d3315c6b55832248cd30c566c081d7 (patch) | |
tree | 16207aacec6e95a9d66a7db9fb994e949a130f03 /net/sunrpc | |
parent | 11d2a1618e377236facdd404113992bde1083914 (diff) |
rpc: clean up decoding of gssproxy linux creds
We can use the normal coding infrastructure here.
Two minor behavior changes:
- we're assuming no wasted space at the end of the linux cred.
That seems to match gss-proxy's behavior, and I can't see why
it would need to do differently in the future.
- NGROUPS_MAX check added: note groups_alloc doesn't do this,
this is the caller's responsibility.
Tested-by: Simo Sorce <simo@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/auth_gss/gss_rpc_xdr.c | 32 |
1 files changed, 13 insertions, 19 deletions
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c index 3c85d1c8a028..f5067b2e0a08 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.c +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c | |||
@@ -166,14 +166,14 @@ static int dummy_dec_opt_array(struct xdr_stream *xdr, | |||
166 | return 0; | 166 | return 0; |
167 | } | 167 | } |
168 | 168 | ||
169 | static int get_s32(void **p, void *max, s32 *res) | 169 | static int get_s32(struct xdr_stream *xdr, s32 *res) |
170 | { | 170 | { |
171 | void *base = *p; | 171 | __be32 *p; |
172 | void *next = (void *)((char *)base + sizeof(s32)); | 172 | |
173 | if (unlikely(next > max || next < base)) | 173 | p = xdr_inline_decode(xdr, 4); |
174 | if (!p) | ||
174 | return -EINVAL; | 175 | return -EINVAL; |
175 | memcpy(res, base, sizeof(s32)); | 176 | memcpy(res, p, sizeof(s32)); |
176 | *p = next; | ||
177 | return 0; | 177 | return 0; |
178 | } | 178 | } |
179 | 179 | ||
@@ -182,7 +182,6 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr, | |||
182 | { | 182 | { |
183 | u32 length; | 183 | u32 length; |
184 | __be32 *p; | 184 | __be32 *p; |
185 | void *q, *end; | ||
186 | s32 tmp; | 185 | s32 tmp; |
187 | int N, i, err; | 186 | int N, i, err; |
188 | 187 | ||
@@ -192,33 +191,28 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr, | |||
192 | 191 | ||
193 | length = be32_to_cpup(p); | 192 | length = be32_to_cpup(p); |
194 | 193 | ||
195 | /* FIXME: we do not want to use the scratch buffer for this one | 194 | if (length > (3 + NGROUPS_MAX) * sizeof(u32)) |
196 | * may need to use functions that allows us to access an io vector | ||
197 | * directly */ | ||
198 | p = xdr_inline_decode(xdr, length); | ||
199 | if (unlikely(p == NULL)) | ||
200 | return -ENOSPC; | 195 | return -ENOSPC; |
201 | 196 | ||
202 | q = p; | ||
203 | end = q + length; | ||
204 | |||
205 | /* uid */ | 197 | /* uid */ |
206 | err = get_s32(&q, end, &tmp); | 198 | err = get_s32(xdr, &tmp); |
207 | if (err) | 199 | if (err) |
208 | return err; | 200 | return err; |
209 | creds->cr_uid = make_kuid(&init_user_ns, tmp); | 201 | creds->cr_uid = make_kuid(&init_user_ns, tmp); |
210 | 202 | ||
211 | /* gid */ | 203 | /* gid */ |
212 | err = get_s32(&q, end, &tmp); | 204 | err = get_s32(xdr, &tmp); |
213 | if (err) | 205 | if (err) |
214 | return err; | 206 | return err; |
215 | creds->cr_gid = make_kgid(&init_user_ns, tmp); | 207 | creds->cr_gid = make_kgid(&init_user_ns, tmp); |
216 | 208 | ||
217 | /* number of additional gid's */ | 209 | /* number of additional gid's */ |
218 | err = get_s32(&q, end, &tmp); | 210 | err = get_s32(xdr, &tmp); |
219 | if (err) | 211 | if (err) |
220 | return err; | 212 | return err; |
221 | N = tmp; | 213 | N = tmp; |
214 | if ((3 + N) * sizeof(u32) != length) | ||
215 | return -EINVAL; | ||
222 | creds->cr_group_info = groups_alloc(N); | 216 | creds->cr_group_info = groups_alloc(N); |
223 | if (creds->cr_group_info == NULL) | 217 | if (creds->cr_group_info == NULL) |
224 | return -ENOMEM; | 218 | return -ENOMEM; |
@@ -226,7 +220,7 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr, | |||
226 | /* gid's */ | 220 | /* gid's */ |
227 | for (i = 0; i < N; i++) { | 221 | for (i = 0; i < N; i++) { |
228 | kgid_t kgid; | 222 | kgid_t kgid; |
229 | err = get_s32(&q, end, &tmp); | 223 | err = get_s32(xdr, &tmp); |
230 | if (err) | 224 | if (err) |
231 | goto out_free_groups; | 225 | goto out_free_groups; |
232 | err = -EINVAL; | 226 | err = -EINVAL; |