From patchwork Fri Jan 21 21:44:20 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shirish Pargaonkar X-Patchwork-Id: 496821 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0LLk0MM030430 for ; Fri, 21 Jan 2011 21:46:01 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753951Ab1AUVqA (ORCPT ); Fri, 21 Jan 2011 16:46:00 -0500 Received: from mail-iy0-f174.google.com ([209.85.210.174]:48276 "EHLO mail-iy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753617Ab1AUVp7 (ORCPT ); Fri, 21 Jan 2011 16:45:59 -0500 Received: by mail-iy0-f174.google.com with SMTP id 18so2123221iyj.19 for ; Fri, 21 Jan 2011 13:45:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer; bh=MfejwSJOMkDPdjXoE0g7NyMLedG/sNxKtwZvZDgfQCs=; b=o5WaUrqwUc2AWRw0UCuJI3AwVLywPuqTdj18eS7w7MlieWt36okyraZf2JxAzZbB1d a+wvEGOutrbuo+ufbJf4k/OQcplBe8TaGxVY0Nt4knnXTLvM1q+oG97Vl8/w2XbM0AvC 6Ylp5l0G9hOBJZ/vGcCN87mNYdImZtPlnrao4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; b=p+1tzVm19pKqVBnY7m6bLCHPcNgxFVumh34pLTIMXFCgYbuka08VWgI2h95orN/gfg E6b4Z4CaVIZfuFf04RmVhBtGBEScg1gi9i8VJsGqdL6WyyHJjWvLV2x/WpOONCxvz1Ud ZkdBNVqKPT3IH0UjoJYWFpSuiJfPYMWlAJtew= Received: by 10.42.229.133 with SMTP id ji5mr1445382icb.477.1295646358691; Fri, 21 Jan 2011 13:45:58 -0800 (PST) Received: from localhost ([32.97.110.58]) by mx.google.com with ESMTPS id 34sm8150814ibi.8.2011.01.21.13.45.58 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 21 Jan 2011 13:45:58 -0800 (PST) From: shirishpargaonkar@gmail.com To: smfrench@gmail.com Cc: linux-cifs@vger.kernel.org, Shirish Pargaonkar Subject: [PATCH 2/3] cifs: Add idmap key and related functions (try #3) Date: Fri, 21 Jan 2011 15:44:20 -0600 Message-Id: <1295646260-21875-1-git-send-email-shirishpargaonkar@gmail.com> X-Mailer: git-send-email 1.6.0.2 Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 21 Jan 2011 21:46:23 +0000 (UTC) diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 1e7636b..8ad2e71 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -23,6 +23,10 @@ #include #include +#include +#include +#include +#include #include "cifspdu.h" #include "cifsglob.h" #include "cifsacl.h" @@ -50,6 +54,96 @@ static const struct cifs_sid sid_authusers = { /* group users */ static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; +const struct cred *root_cred; + +static int +cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) +{ + char *payload; + + payload = kmalloc(datalen, GFP_KERNEL); + if (!payload) + return -ENOMEM; + + memcpy(payload, data, datalen); + key->payload.data = payload; + return 0; +} + +static inline void +cifs_idmap_key_destroy(struct key *key) +{ + kfree(key->payload.data); +} + +struct key_type cifs_idmap_key_type = { + .name = "cifs.cifs_idmap", + .instantiate = cifs_idmap_key_instantiate, + .destroy = cifs_idmap_key_destroy, + .describe = user_describe, + .match = user_match, +}; + +int +init_cifs_idmap(void) +{ + struct cred *cred; + struct key *keyring; + int ret; + + cFYI(1, "Registering the %s key type\n", cifs_idmap_key_type.name); + + /* create an override credential set with a special thread keyring in + * which DNS requests are cached + * + * this is used to prevent malicious redirections from being installed + * with add_key(). + */ + cred = prepare_kernel_cred(NULL); + if (!cred) + return -ENOMEM; + + keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred, + (KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW | KEY_USR_READ, + KEY_ALLOC_NOT_IN_QUOTA); + if (IS_ERR(keyring)) { + ret = PTR_ERR(keyring); + goto failed_put_cred; + } + + ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL); + if (ret < 0) + goto failed_put_key; + + ret = register_key_type(&cifs_idmap_key_type); + if (ret < 0) + goto failed_put_key; + + /* instruct request_key() to use this special keyring as a cache for + * the results it looks up */ + cred->thread_keyring = keyring; + cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; + root_cred = cred; + + cFYI(1, "DNS resolver keyring: %d\n", key_serial(keyring)); + return 0; + +failed_put_key: + key_put(keyring); +failed_put_cred: + put_cred(cred); + return ret; +} + +void +exit_cifs_idmap(void) +{ + key_revoke(root_cred->thread_keyring); + unregister_key_type(&cifs_idmap_key_type); + put_cred(root_cred); + cFYI(1, "Unregistered %s key type\n", cifs_idmap_key_type.name); +} int match_sid(struct cifs_sid *ctsid) { diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index 6c26e7f..3851883 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h @@ -80,6 +80,11 @@ struct cifs_sid_id { unsigned long id; } __attribute__((packed)); +#ifdef __KERNEL__ +extern struct key_type cifs_idmap_key_type; +extern const struct cred *root_cred; +#endif /* KERNEL */ + extern int match_sid(struct cifs_sid *); extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *); diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 36182e3..08563cb 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -1039,11 +1039,16 @@ init_cifs(void) rc = register_key_type(&cifs_spnego_key_type); if (rc) goto out_unregister_filesystem; + rc = init_cifs_idmap(); + if (rc) + goto out_unregister_keytype; #endif return 0; #ifdef CONFIG_CIFS_UPCALL +out_unregister_keytype: + unregister_key_type(&cifs_spnego_key_type); out_unregister_filesystem: unregister_filesystem(&cifs_fs_type); #endif @@ -1070,6 +1075,7 @@ exit_cifs(void) cifs_dfs_release_automount_timer(); #endif #ifdef CONFIG_CIFS_UPCALL + exit_cifs_idmap(); unregister_key_type(&cifs_spnego_key_type); #endif unregister_filesystem(&cifs_fs_type); diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 982895f..d311019 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -53,6 +53,8 @@ do { \ cFYI(1, "CIFS VFS: leaving %s (xid = %d) rc = %d", \ __func__, curr_xid, (int)rc); \ } while (0) +extern int init_cifs_idmap(void); +extern void exit_cifs_idmap(void); extern char *build_path_from_dentry(struct dentry *); extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, struct cifsTconInfo *tcon); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 18d3c77..ac6f536 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3099,6 +3099,18 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) } spin_unlock(&cifs_sb->tlink_tree_lock); + root = &cifs_sb->uidtree; + spin_lock(&cifs_sb->siduidlock); + while ((node = rb_first(root))) + rb_erase(node, root); + spin_unlock(&cifs_sb->siduidlock); + + root = &cifs_sb->gidtree; + spin_lock(&cifs_sb->sidgidlock); + while ((node = rb_first(root))) + rb_erase(node, root); + spin_unlock(&cifs_sb->sidgidlock); + tmp = cifs_sb->prepath; cifs_sb->prepathlen = 0; cifs_sb->prepath = NULL;