aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-05-20 11:20:27 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-06-06 16:24:36 -0400
commitab7cb0dfab0baa63f9a1faa7441b90b07881a9c7 (patch)
tree9690f481aaeaf2d9f60b43a50f0ce22b2e69b381
parent965e9c23de1c69a9fae2e68679027d01685530c4 (diff)
NFSv4.1: Ensure that test_stateid and free_stateid use correct credentials
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs4proc.c65
1 files changed, 50 insertions, 15 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d94af83171af..e4398e8f512a 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -83,8 +83,10 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
83 struct nfs_fattr *fattr, struct iattr *sattr, 83 struct nfs_fattr *fattr, struct iattr *sattr,
84 struct nfs4_state *state); 84 struct nfs4_state *state);
85#ifdef CONFIG_NFS_V4_1 85#ifdef CONFIG_NFS_V4_1
86static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *); 86static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *,
87static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *); 87 struct rpc_cred *);
88static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *,
89 struct rpc_cred *);
88#endif 90#endif
89/* Prevent leaks of NFSv4 errors into userland */ 91/* Prevent leaks of NFSv4 errors into userland */
90static int nfs4_map_errors(int err) 92static int nfs4_map_errors(int err)
@@ -1855,18 +1857,30 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state)
1855{ 1857{
1856 struct nfs_server *server = NFS_SERVER(state->inode); 1858 struct nfs_server *server = NFS_SERVER(state->inode);
1857 nfs4_stateid *stateid = &state->stateid; 1859 nfs4_stateid *stateid = &state->stateid;
1858 int status; 1860 struct nfs_delegation *delegation;
1861 struct rpc_cred *cred = NULL;
1862 int status = -NFS4ERR_BAD_STATEID;
1859 1863
1860 /* If a state reset has been done, test_stateid is unneeded */ 1864 /* If a state reset has been done, test_stateid is unneeded */
1861 if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) 1865 if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
1862 return; 1866 return;
1863 1867
1864 status = nfs41_test_stateid(server, stateid); 1868 /* Get the delegation credential for use by test/free_stateid */
1869 rcu_read_lock();
1870 delegation = rcu_dereference(NFS_I(state->inode)->delegation);
1871 if (delegation != NULL &&
1872 nfs4_stateid_match(&delegation->stateid, stateid)) {
1873 cred = get_rpccred(delegation->cred);
1874 rcu_read_unlock();
1875 status = nfs41_test_stateid(server, stateid, cred);
1876 } else
1877 rcu_read_unlock();
1878
1865 if (status != NFS_OK) { 1879 if (status != NFS_OK) {
1866 /* Free the stateid unless the server explicitly 1880 /* Free the stateid unless the server explicitly
1867 * informs us the stateid is unrecognized. */ 1881 * informs us the stateid is unrecognized. */
1868 if (status != -NFS4ERR_BAD_STATEID) 1882 if (status != -NFS4ERR_BAD_STATEID)
1869 nfs41_free_stateid(server, stateid); 1883 nfs41_free_stateid(server, stateid, cred);
1870 nfs_remove_bad_delegation(state->inode); 1884 nfs_remove_bad_delegation(state->inode);
1871 1885
1872 write_seqlock(&state->seqlock); 1886 write_seqlock(&state->seqlock);
@@ -1874,6 +1888,9 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state)
1874 write_sequnlock(&state->seqlock); 1888 write_sequnlock(&state->seqlock);
1875 clear_bit(NFS_DELEGATED_STATE, &state->flags); 1889 clear_bit(NFS_DELEGATED_STATE, &state->flags);
1876 } 1890 }
1891
1892 if (cred != NULL)
1893 put_rpccred(cred);
1877} 1894}
1878 1895
1879/** 1896/**
@@ -1888,6 +1905,7 @@ static int nfs41_check_open_stateid(struct nfs4_state *state)
1888{ 1905{
1889 struct nfs_server *server = NFS_SERVER(state->inode); 1906 struct nfs_server *server = NFS_SERVER(state->inode);
1890 nfs4_stateid *stateid = &state->open_stateid; 1907 nfs4_stateid *stateid = &state->open_stateid;
1908 struct rpc_cred *cred = state->owner->so_cred;
1891 int status; 1909 int status;
1892 1910
1893 /* If a state reset has been done, test_stateid is unneeded */ 1911 /* If a state reset has been done, test_stateid is unneeded */
@@ -1896,12 +1914,12 @@ static int nfs41_check_open_stateid(struct nfs4_state *state)
1896 (test_bit(NFS_O_RDWR_STATE, &state->flags) == 0)) 1914 (test_bit(NFS_O_RDWR_STATE, &state->flags) == 0))
1897 return -NFS4ERR_BAD_STATEID; 1915 return -NFS4ERR_BAD_STATEID;
1898 1916
1899 status = nfs41_test_stateid(server, stateid); 1917 status = nfs41_test_stateid(server, stateid, cred);
1900 if (status != NFS_OK) { 1918 if (status != NFS_OK) {
1901 /* Free the stateid unless the server explicitly 1919 /* Free the stateid unless the server explicitly
1902 * informs us the stateid is unrecognized. */ 1920 * informs us the stateid is unrecognized. */
1903 if (status != -NFS4ERR_BAD_STATEID) 1921 if (status != -NFS4ERR_BAD_STATEID)
1904 nfs41_free_stateid(server, stateid); 1922 nfs41_free_stateid(server, stateid, cred);
1905 1923
1906 clear_bit(NFS_O_RDONLY_STATE, &state->flags); 1924 clear_bit(NFS_O_RDONLY_STATE, &state->flags);
1907 clear_bit(NFS_O_WRONLY_STATE, &state->flags); 1925 clear_bit(NFS_O_WRONLY_STATE, &state->flags);
@@ -5056,13 +5074,18 @@ static int nfs41_check_expired_locks(struct nfs4_state *state)
5056 5074
5057 list_for_each_entry(lsp, &state->lock_states, ls_locks) { 5075 list_for_each_entry(lsp, &state->lock_states, ls_locks) {
5058 if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { 5076 if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
5059 status = nfs41_test_stateid(server, &lsp->ls_stateid); 5077 struct rpc_cred *cred = lsp->ls_state->owner->so_cred;
5078
5079 status = nfs41_test_stateid(server,
5080 &lsp->ls_stateid,
5081 cred);
5060 if (status != NFS_OK) { 5082 if (status != NFS_OK) {
5061 /* Free the stateid unless the server 5083 /* Free the stateid unless the server
5062 * informs us the stateid is unrecognized. */ 5084 * informs us the stateid is unrecognized. */
5063 if (status != -NFS4ERR_BAD_STATEID) 5085 if (status != -NFS4ERR_BAD_STATEID)
5064 nfs41_free_stateid(server, 5086 nfs41_free_stateid(server,
5065 &lsp->ls_stateid); 5087 &lsp->ls_stateid,
5088 cred);
5066 clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags); 5089 clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags);
5067 ret = status; 5090 ret = status;
5068 } 5091 }
@@ -6737,7 +6760,9 @@ out:
6737 return err; 6760 return err;
6738} 6761}
6739 6762
6740static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) 6763static int _nfs41_test_stateid(struct nfs_server *server,
6764 nfs4_stateid *stateid,
6765 struct rpc_cred *cred)
6741{ 6766{
6742 int status; 6767 int status;
6743 struct nfs41_test_stateid_args args = { 6768 struct nfs41_test_stateid_args args = {
@@ -6748,6 +6773,7 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid)
6748 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID], 6773 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_TEST_STATEID],
6749 .rpc_argp = &args, 6774 .rpc_argp = &args,
6750 .rpc_resp = &res, 6775 .rpc_resp = &res,
6776 .rpc_cred = cred,
6751 }; 6777 };
6752 6778
6753 dprintk("NFS call test_stateid %p\n", stateid); 6779 dprintk("NFS call test_stateid %p\n", stateid);
@@ -6768,17 +6794,20 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid)
6768 * 6794 *
6769 * @server: server / transport on which to perform the operation 6795 * @server: server / transport on which to perform the operation
6770 * @stateid: state ID to test 6796 * @stateid: state ID to test
6797 * @cred: credential
6771 * 6798 *
6772 * Returns NFS_OK if the server recognizes that "stateid" is valid. 6799 * Returns NFS_OK if the server recognizes that "stateid" is valid.
6773 * Otherwise a negative NFS4ERR value is returned if the operation 6800 * Otherwise a negative NFS4ERR value is returned if the operation
6774 * failed or the state ID is not currently valid. 6801 * failed or the state ID is not currently valid.
6775 */ 6802 */
6776static int nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) 6803static int nfs41_test_stateid(struct nfs_server *server,
6804 nfs4_stateid *stateid,
6805 struct rpc_cred *cred)
6777{ 6806{
6778 struct nfs4_exception exception = { }; 6807 struct nfs4_exception exception = { };
6779 int err; 6808 int err;
6780 do { 6809 do {
6781 err = _nfs41_test_stateid(server, stateid); 6810 err = _nfs41_test_stateid(server, stateid, cred);
6782 if (err != -NFS4ERR_DELAY) 6811 if (err != -NFS4ERR_DELAY)
6783 break; 6812 break;
6784 nfs4_handle_exception(server, err, &exception); 6813 nfs4_handle_exception(server, err, &exception);
@@ -6827,10 +6856,12 @@ const struct rpc_call_ops nfs41_free_stateid_ops = {
6827 6856
6828static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server, 6857static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server,
6829 nfs4_stateid *stateid, 6858 nfs4_stateid *stateid,
6859 struct rpc_cred *cred,
6830 bool privileged) 6860 bool privileged)
6831{ 6861{
6832 struct rpc_message msg = { 6862 struct rpc_message msg = {
6833 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID], 6863 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FREE_STATEID],
6864 .rpc_cred = cred,
6834 }; 6865 };
6835 struct rpc_task_setup task_setup = { 6866 struct rpc_task_setup task_setup = {
6836 .rpc_client = server->client, 6867 .rpc_client = server->client,
@@ -6863,16 +6894,19 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server,
6863 * 6894 *
6864 * @server: server / transport on which to perform the operation 6895 * @server: server / transport on which to perform the operation
6865 * @stateid: state ID to release 6896 * @stateid: state ID to release
6897 * @cred: credential
6866 * 6898 *
6867 * Returns NFS_OK if the server freed "stateid". Otherwise a 6899 * Returns NFS_OK if the server freed "stateid". Otherwise a
6868 * negative NFS4ERR value is returned. 6900 * negative NFS4ERR value is returned.
6869 */ 6901 */
6870static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) 6902static int nfs41_free_stateid(struct nfs_server *server,
6903 nfs4_stateid *stateid,
6904 struct rpc_cred *cred)
6871{ 6905{
6872 struct rpc_task *task; 6906 struct rpc_task *task;
6873 int ret; 6907 int ret;
6874 6908
6875 task = _nfs41_free_stateid(server, stateid, true); 6909 task = _nfs41_free_stateid(server, stateid, cred, true);
6876 if (IS_ERR(task)) 6910 if (IS_ERR(task))
6877 return PTR_ERR(task); 6911 return PTR_ERR(task);
6878 ret = rpc_wait_for_completion_task(task); 6912 ret = rpc_wait_for_completion_task(task);
@@ -6885,8 +6919,9 @@ static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid)
6885static int nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp) 6919static int nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp)
6886{ 6920{
6887 struct rpc_task *task; 6921 struct rpc_task *task;
6922 struct rpc_cred *cred = lsp->ls_state->owner->so_cred;
6888 6923
6889 task = _nfs41_free_stateid(server, &lsp->ls_stateid, false); 6924 task = _nfs41_free_stateid(server, &lsp->ls_stateid, cred, false);
6890 nfs4_free_lock_state(server, lsp); 6925 nfs4_free_lock_state(server, lsp);
6891 if (IS_ERR(task)) 6926 if (IS_ERR(task))
6892 return PTR_ERR(task); 6927 return PTR_ERR(task);