diff options
author | Kinglong Mee <kinglongmee@gmail.com> | 2013-12-31 11:35:47 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-01-06 15:33:54 -0500 |
commit | 60810e5489dffd0bd12e4f99fe9fc330c9a636e1 (patch) | |
tree | 74bb2c76dfd59abd388551c63f406bce04e6f224 /fs/nfsd/nfs4state.c | |
parent | 0fdc26785d0a5bb33d9adb572307fd2d7a406734 (diff) |
NFSD: Fix a memory leak in nfsd4_create_session
If failed after calling alloc_session but before init_session, nfsd will call __free_session to
free se_slots in session. But, session->se_fchannel.maxreqs is not initialized (value is zero).
So that, the memory malloced for slots will be lost in free_session_slots for maxreqs is zero.
This path sets the information for channel in alloc_session after mallocing slots succeed,
instead in init_session.
Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index acb95026ae3b..5795d5f58f41 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -832,10 +832,11 @@ static void nfsd4_put_drc_mem(struct nfsd4_channel_attrs *ca) | |||
832 | spin_unlock(&nfsd_drc_lock); | 832 | spin_unlock(&nfsd_drc_lock); |
833 | } | 833 | } |
834 | 834 | ||
835 | static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *attrs) | 835 | static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs, |
836 | struct nfsd4_channel_attrs *battrs) | ||
836 | { | 837 | { |
837 | int numslots = attrs->maxreqs; | 838 | int numslots = fattrs->maxreqs; |
838 | int slotsize = slot_bytes(attrs); | 839 | int slotsize = slot_bytes(fattrs); |
839 | struct nfsd4_session *new; | 840 | struct nfsd4_session *new; |
840 | int mem, i; | 841 | int mem, i; |
841 | 842 | ||
@@ -852,6 +853,10 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *attrs) | |||
852 | if (!new->se_slots[i]) | 853 | if (!new->se_slots[i]) |
853 | goto out_free; | 854 | goto out_free; |
854 | } | 855 | } |
856 | |||
857 | memcpy(&new->se_fchannel, fattrs, sizeof(struct nfsd4_channel_attrs)); | ||
858 | memcpy(&new->se_bchannel, battrs, sizeof(struct nfsd4_channel_attrs)); | ||
859 | |||
855 | return new; | 860 | return new; |
856 | out_free: | 861 | out_free: |
857 | while (i--) | 862 | while (i--) |
@@ -997,10 +1002,7 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru | |||
997 | list_add(&new->se_perclnt, &clp->cl_sessions); | 1002 | list_add(&new->se_perclnt, &clp->cl_sessions); |
998 | spin_unlock(&clp->cl_lock); | 1003 | spin_unlock(&clp->cl_lock); |
999 | spin_unlock(&nn->client_lock); | 1004 | spin_unlock(&nn->client_lock); |
1000 | memcpy(&new->se_fchannel, &cses->fore_channel, | 1005 | |
1001 | sizeof(struct nfsd4_channel_attrs)); | ||
1002 | memcpy(&new->se_bchannel, &cses->back_channel, | ||
1003 | sizeof(struct nfsd4_channel_attrs)); | ||
1004 | if (cses->flags & SESSION4_BACK_CHAN) { | 1006 | if (cses->flags & SESSION4_BACK_CHAN) { |
1005 | struct sockaddr *sa = svc_addr(rqstp); | 1007 | struct sockaddr *sa = svc_addr(rqstp); |
1006 | /* | 1008 | /* |
@@ -1922,7 +1924,7 @@ nfsd4_create_session(struct svc_rqst *rqstp, | |||
1922 | if (status) | 1924 | if (status) |
1923 | goto out_release_drc_mem; | 1925 | goto out_release_drc_mem; |
1924 | status = nfserr_jukebox; | 1926 | status = nfserr_jukebox; |
1925 | new = alloc_session(&cr_ses->fore_channel); | 1927 | new = alloc_session(&cr_ses->fore_channel, &cr_ses->back_channel); |
1926 | if (!new) | 1928 | if (!new) |
1927 | goto out_release_drc_mem; | 1929 | goto out_release_drc_mem; |
1928 | conn = alloc_conn_from_crses(rqstp, cr_ses); | 1930 | conn = alloc_conn_from_crses(rqstp, cr_ses); |