Fix large order rpc allocations (rhbz 997705)
- Fix multimedia keys on Genius GX keyboard (rhbz 928561)
This commit is contained in:
parent
1b87d09575
commit
80641a0bb8
13
kernel.spec
13
kernel.spec
@ -763,6 +763,12 @@ Patch25104: ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch
|
||||
#rhbz 928561
|
||||
Patch25105: 0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch
|
||||
|
||||
#rhbz 997705
|
||||
Patch25110: rpc-clean-up-decoding-of-gssproxy-linux-creds.patch
|
||||
Patch25111: rpc-comment-on-linux_cred-encoding-treat-all-as-unsigned.patch
|
||||
Patch25112: rpc-fix-huge-kmallocs-in-gss-proxy.patch
|
||||
Patch25113: rpc-let-xdr-layer-allocate-gssproxy-receieve-pages.patch
|
||||
|
||||
# END OF PATCH DEFINITIONS
|
||||
|
||||
%endif
|
||||
@ -1474,6 +1480,12 @@ ApplyPatch ansi_cprng-Fix-off-by-one-error-in-non-block-size-request.patch
|
||||
#rhbz 928561
|
||||
ApplyPatch 0001-HID-kye-Add-report-fixup-for-Genius-Gx-Imperator-Key.patch
|
||||
|
||||
#rhbz 997705
|
||||
ApplyPatch rpc-clean-up-decoding-of-gssproxy-linux-creds.patch
|
||||
ApplyPatch rpc-comment-on-linux_cred-encoding-treat-all-as-unsigned.patch
|
||||
ApplyPatch rpc-fix-huge-kmallocs-in-gss-proxy.patch
|
||||
ApplyPatch rpc-let-xdr-layer-allocate-gssproxy-receieve-pages.patch
|
||||
|
||||
# END OF PATCH APPLICATIONS
|
||||
|
||||
%endif
|
||||
@ -2287,6 +2299,7 @@ fi
|
||||
|
||||
%changelog
|
||||
* Fri Sep 20 2013 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- Fix large order rpc allocations (rhbz 997705)
|
||||
- Fix multimedia keys on Genius GX keyboard (rhbz 928561)
|
||||
|
||||
* Tue Sep 17 2013 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
|
110
rpc-clean-up-decoding-of-gssproxy-linux-creds.patch
Normal file
110
rpc-clean-up-decoding-of-gssproxy-linux-creds.patch
Normal file
@ -0,0 +1,110 @@
|
||||
From: "J. Bruce Fields" <bfields@redhat.com>
|
||||
|
||||
commit 778e512bb1d3315c6b55832248cd30c566c081d7 upstream.
|
||||
|
||||
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>
|
||||
---
|
||||
net/sunrpc/auth_gss/gss_rpc_xdr.c | 32 +++++++++++++-------------------
|
||||
1 file 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 3c85d1c..f5067b2 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,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int get_s32(void **p, void *max, s32 *res)
|
||||
+static int get_s32(struct xdr_stream *xdr, s32 *res)
|
||||
{
|
||||
- void *base = *p;
|
||||
- void *next = (void *)((char *)base + sizeof(s32));
|
||||
- if (unlikely(next > max || next < base))
|
||||
+ __be32 *p;
|
||||
+
|
||||
+ p = xdr_inline_decode(xdr, 4);
|
||||
+ if (!p)
|
||||
return -EINVAL;
|
||||
- memcpy(res, base, sizeof(s32));
|
||||
- *p = next;
|
||||
+ memcpy(res, p, sizeof(s32));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -182,7 +182,6 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr,
|
||||
{
|
||||
u32 length;
|
||||
__be32 *p;
|
||||
- void *q, *end;
|
||||
s32 tmp;
|
||||
int N, i, err;
|
||||
|
||||
@@ -192,33 +191,28 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr,
|
||||
|
||||
length = be32_to_cpup(p);
|
||||
|
||||
- /* FIXME: we do not want to use the scratch buffer for this one
|
||||
- * may need to use functions that allows us to access an io vector
|
||||
- * directly */
|
||||
- p = xdr_inline_decode(xdr, length);
|
||||
- if (unlikely(p == NULL))
|
||||
+ if (length > (3 + NGROUPS_MAX) * sizeof(u32))
|
||||
return -ENOSPC;
|
||||
|
||||
- q = p;
|
||||
- end = q + length;
|
||||
-
|
||||
/* uid */
|
||||
- err = get_s32(&q, end, &tmp);
|
||||
+ err = get_s32(xdr, &tmp);
|
||||
if (err)
|
||||
return err;
|
||||
creds->cr_uid = make_kuid(&init_user_ns, tmp);
|
||||
|
||||
/* gid */
|
||||
- err = get_s32(&q, end, &tmp);
|
||||
+ err = get_s32(xdr, &tmp);
|
||||
if (err)
|
||||
return err;
|
||||
creds->cr_gid = make_kgid(&init_user_ns, tmp);
|
||||
|
||||
/* number of additional gid's */
|
||||
- err = get_s32(&q, end, &tmp);
|
||||
+ err = get_s32(xdr, &tmp);
|
||||
if (err)
|
||||
return err;
|
||||
N = tmp;
|
||||
+ if ((3 + N) * sizeof(u32) != length)
|
||||
+ return -EINVAL;
|
||||
creds->cr_group_info = groups_alloc(N);
|
||||
if (creds->cr_group_info == NULL)
|
||||
return -ENOMEM;
|
||||
@@ -226,7 +220,7 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr,
|
||||
/* gid's */
|
||||
for (i = 0; i < N; i++) {
|
||||
kgid_t kgid;
|
||||
- err = get_s32(&q, end, &tmp);
|
||||
+ err = get_s32(xdr, &tmp);
|
||||
if (err)
|
||||
goto out_free_groups;
|
||||
err = -EINVAL;
|
||||
--
|
||||
1.7.9.5
|
||||
|
||||
--
|
||||
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
|
||||
the body of a message to majordomo@vger.kernel.org
|
||||
More majordomo info at http://vger.kernel.org/majordomo-info.html
|
@ -0,0 +1,90 @@
|
||||
From: "J. Bruce Fields" <bfields@redhat.com>
|
||||
|
||||
commit 6a36978e6931e6601be586eb313375335f2cfaa3 upstream.
|
||||
|
||||
The encoding of linux creds is a bit confusing.
|
||||
|
||||
Also: I think in practice it doesn't really matter whether we treat any
|
||||
of these things as signed or unsigned, but unsigned seems more
|
||||
straightforward: uid_t/gid_t are unsigned and it simplifies the ngroups
|
||||
overflow check.
|
||||
|
||||
Tested-by: Simo Sorce <simo@redhat.com>
|
||||
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
|
||||
---
|
||||
net/sunrpc/auth_gss/gss_rpc_xdr.c | 18 ++++++++++--------
|
||||
1 file changed, 10 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c
|
||||
index f5067b2..3c19c7d 100644
|
||||
--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c
|
||||
+++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c
|
||||
@@ -166,14 +166,15 @@ static int dummy_dec_opt_array(struct xdr_stream *xdr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int get_s32(struct xdr_stream *xdr, s32 *res)
|
||||
+static int get_host_u32(struct xdr_stream *xdr, u32 *res)
|
||||
{
|
||||
__be32 *p;
|
||||
|
||||
p = xdr_inline_decode(xdr, 4);
|
||||
if (!p)
|
||||
return -EINVAL;
|
||||
- memcpy(res, p, sizeof(s32));
|
||||
+ /* Contents of linux creds are all host-endian: */
|
||||
+ memcpy(res, p, sizeof(u32));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -182,8 +183,9 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr,
|
||||
{
|
||||
u32 length;
|
||||
__be32 *p;
|
||||
- s32 tmp;
|
||||
- int N, i, err;
|
||||
+ u32 tmp;
|
||||
+ u32 N;
|
||||
+ int i, err;
|
||||
|
||||
p = xdr_inline_decode(xdr, 4);
|
||||
if (unlikely(p == NULL))
|
||||
@@ -195,19 +197,19 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr,
|
||||
return -ENOSPC;
|
||||
|
||||
/* uid */
|
||||
- err = get_s32(xdr, &tmp);
|
||||
+ err = get_host_u32(xdr, &tmp);
|
||||
if (err)
|
||||
return err;
|
||||
creds->cr_uid = make_kuid(&init_user_ns, tmp);
|
||||
|
||||
/* gid */
|
||||
- err = get_s32(xdr, &tmp);
|
||||
+ err = get_host_u32(xdr, &tmp);
|
||||
if (err)
|
||||
return err;
|
||||
creds->cr_gid = make_kgid(&init_user_ns, tmp);
|
||||
|
||||
/* number of additional gid's */
|
||||
- err = get_s32(xdr, &tmp);
|
||||
+ err = get_host_u32(xdr, &tmp);
|
||||
if (err)
|
||||
return err;
|
||||
N = tmp;
|
||||
@@ -220,7 +222,7 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr,
|
||||
/* gid's */
|
||||
for (i = 0; i < N; i++) {
|
||||
kgid_t kgid;
|
||||
- err = get_s32(xdr, &tmp);
|
||||
+ err = get_host_u32(xdr, &tmp);
|
||||
if (err)
|
||||
goto out_free_groups;
|
||||
err = -EINVAL;
|
||||
--
|
||||
1.7.9.5
|
||||
|
||||
--
|
||||
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
|
||||
the body of a message to majordomo@vger.kernel.org
|
||||
More majordomo info at http://vger.kernel.org/majordomo-info.html
|
113
rpc-fix-huge-kmallocs-in-gss-proxy.patch
Normal file
113
rpc-fix-huge-kmallocs-in-gss-proxy.patch
Normal file
@ -0,0 +1,113 @@
|
||||
From: "J. Bruce Fields" <bfields@redhat.com>
|
||||
|
||||
commit 9dfd87da1aeb0fd364167ad199f40fe96a6a87be upstream.
|
||||
|
||||
The reply to a gssproxy can include up to NGROUPS_MAX gid's, which will
|
||||
take up more than a page. We therefore need to allocate an array of
|
||||
pages to hold the reply instead of trying to allocate a single huge
|
||||
buffer.
|
||||
|
||||
Tested-by: Simo Sorce <simo@redhat.com>
|
||||
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
|
||||
---
|
||||
net/sunrpc/auth_gss/gss_rpc_upcall.c | 30 ++++++++++++++++++++++++++++++
|
||||
net/sunrpc/auth_gss/gss_rpc_xdr.c | 3 +++
|
||||
net/sunrpc/auth_gss/gss_rpc_xdr.h | 5 ++++-
|
||||
3 files changed, 37 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
|
||||
index af7ffd4..be95af3 100644
|
||||
--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
|
||||
+++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
|
||||
@@ -213,6 +213,30 @@ static int gssp_call(struct net *net, struct rpc_message *msg)
|
||||
return status;
|
||||
}
|
||||
|
||||
+static void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < arg->npages && arg->pages[i]; i++)
|
||||
+ __free_page(arg->pages[i]);
|
||||
+}
|
||||
+
|
||||
+static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE);
|
||||
+ arg->pages = kzalloc(arg->npages * sizeof(struct page *), GFP_KERNEL);
|
||||
+
|
||||
+ for (i=0; i < arg->npages; i++) {
|
||||
+ arg->pages[i] = alloc_page(GFP_KERNEL);
|
||||
+ if (arg->pages[i] == NULL) {
|
||||
+ gssp_free_receive_pages(arg);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
|
||||
/*
|
||||
* Public functions
|
||||
@@ -261,10 +285,16 @@ int gssp_accept_sec_context_upcall(struct net *net,
|
||||
arg.context_handle = &ctxh;
|
||||
res.output_token->len = GSSX_max_output_token_sz;
|
||||
|
||||
+ ret = gssp_alloc_receive_pages(&arg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
/* use nfs/ for targ_name ? */
|
||||
|
||||
ret = gssp_call(net, &msg);
|
||||
|
||||
+ gssp_free_receive_pages(&arg);
|
||||
+
|
||||
/* we need to fetch all data even in case of error so
|
||||
* that we can free special strctures is they have been allocated */
|
||||
data->major_status = res.status.major_status;
|
||||
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c
|
||||
index 3c19c7d..f0f78c5 100644
|
||||
--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c
|
||||
+++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c
|
||||
@@ -780,6 +780,9 @@ void gssx_enc_accept_sec_context(struct rpc_rqst *req,
|
||||
/* arg->options */
|
||||
err = dummy_enc_opt_array(xdr, &arg->options);
|
||||
|
||||
+ xdr_inline_pages(&req->rq_rcv_buf,
|
||||
+ PAGE_SIZE/2 /* pretty arbitrary */,
|
||||
+ arg->pages, 0 /* page base */, arg->npages * PAGE_SIZE);
|
||||
done:
|
||||
if (err)
|
||||
dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err);
|
||||
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.h b/net/sunrpc/auth_gss/gss_rpc_xdr.h
|
||||
index 1c98b27..685a688 100644
|
||||
--- a/net/sunrpc/auth_gss/gss_rpc_xdr.h
|
||||
+++ b/net/sunrpc/auth_gss/gss_rpc_xdr.h
|
||||
@@ -147,6 +147,8 @@ struct gssx_arg_accept_sec_context {
|
||||
struct gssx_cb *input_cb;
|
||||
u32 ret_deleg_cred;
|
||||
struct gssx_option_array options;
|
||||
+ struct page **pages;
|
||||
+ unsigned int npages;
|
||||
};
|
||||
|
||||
struct gssx_res_accept_sec_context {
|
||||
@@ -240,7 +242,8 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
|
||||
2 * GSSX_max_princ_sz + \
|
||||
8 + 8 + 4 + 4 + 4)
|
||||
#define GSSX_max_output_token_sz 1024
|
||||
-#define GSSX_max_creds_sz (4 + 4 + 4 + NGROUPS_MAX * 4)
|
||||
+/* grouplist not included; we allocate separate pages for that: */
|
||||
+#define GSSX_max_creds_sz (4 + 4 + 4 /* + NGROUPS_MAX*4 */)
|
||||
#define GSSX_RES_accept_sec_context_sz (GSSX_default_status_sz + \
|
||||
GSSX_default_ctx_sz + \
|
||||
GSSX_max_output_token_sz + \
|
||||
--
|
||||
1.7.9.5
|
||||
|
||||
--
|
||||
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
|
||||
the body of a message to majordomo@vger.kernel.org
|
||||
More majordomo info at http://vger.kernel.org/majordomo-info.html
|
52
rpc-let-xdr-layer-allocate-gssproxy-receieve-pages.patch
Normal file
52
rpc-let-xdr-layer-allocate-gssproxy-receieve-pages.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From: "J. Bruce Fields" <bfields@redhat.com>
|
||||
|
||||
commit d4a516560fc96a9d486a9939bcb567e3fdce8f49 upstream.
|
||||
|
||||
In theory the linux cred in a gssproxy reply can include up to
|
||||
NGROUPS_MAX data, 256K of data. In the common case we expect it to be
|
||||
shorter. So do as the nfsv3 ACL code does and let the xdr code allocate
|
||||
the pages as they come in, instead of allocating a lot of pages that
|
||||
won't typically be used.
|
||||
|
||||
Tested-by: Simo Sorce <simo@redhat.com>
|
||||
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
|
||||
---
|
||||
net/sunrpc/auth_gss/gss_rpc_upcall.c | 16 ++++++----------
|
||||
1 file changed, 6 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
|
||||
index be95af3..f1eb0d1 100644
|
||||
--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
|
||||
+++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
|
||||
@@ -223,18 +223,14 @@ static void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg)
|
||||
|
||||
static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg)
|
||||
{
|
||||
- int i;
|
||||
-
|
||||
arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE);
|
||||
arg->pages = kzalloc(arg->npages * sizeof(struct page *), GFP_KERNEL);
|
||||
-
|
||||
- for (i=0; i < arg->npages; i++) {
|
||||
- arg->pages[i] = alloc_page(GFP_KERNEL);
|
||||
- if (arg->pages[i] == NULL) {
|
||||
- gssp_free_receive_pages(arg);
|
||||
- return -ENOMEM;
|
||||
- }
|
||||
- }
|
||||
+ /*
|
||||
+ * XXX: actual pages are allocated by xdr layer in
|
||||
+ * xdr_partial_copy_from_skb.
|
||||
+ */
|
||||
+ if (!arg->pages)
|
||||
+ return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
||||
--
|
||||
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
|
||||
the body of a message to majordomo@vger.kernel.org
|
||||
More majordomo info at http://vger.kernel.org/majordomo-info.html
|
Loading…
Reference in New Issue
Block a user