Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 201152
b: refs/heads/master
c: 4c0c03c
h: refs/heads/master
v: v3
  • Loading branch information
David Howells authored and Linus Torvalds committed Jul 22, 2010
1 parent 17bac3a commit 2d01b5c
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cd5b8f8755a89a57fc8c408d284b8b613f090345
refs/heads/master: 4c0c03ca54f72fdd5912516ad0a23ec5cf01bda7
6 changes: 3 additions & 3 deletions trunk/fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,7 @@ init_cifs(void)
goto out_unregister_filesystem;
#endif
#ifdef CONFIG_CIFS_DFS_UPCALL
rc = register_key_type(&key_type_dns_resolver);
rc = cifs_init_dns_resolver();
if (rc)
goto out_unregister_key_type;
#endif
Expand All @@ -935,7 +935,7 @@ init_cifs(void)

out_unregister_resolver_key:
#ifdef CONFIG_CIFS_DFS_UPCALL
unregister_key_type(&key_type_dns_resolver);
cifs_exit_dns_resolver();
out_unregister_key_type:
#endif
#ifdef CONFIG_CIFS_UPCALL
Expand All @@ -961,7 +961,7 @@ exit_cifs(void)
cifs_proc_clean();
#ifdef CONFIG_CIFS_DFS_UPCALL
cifs_dfs_release_automount_timer();
unregister_key_type(&key_type_dns_resolver);
cifs_exit_dns_resolver();
#endif
#ifdef CONFIG_CIFS_UPCALL
unregister_key_type(&cifs_spnego_key_type);
Expand Down
69 changes: 69 additions & 0 deletions trunk/fs/cifs/dns_resolve.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,16 @@
*/

#include <linux/slab.h>
#include <linux/keyctl.h>
#include <linux/key-type.h>
#include <keys/user-type.h>
#include "dns_resolve.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_debug.h"

static const struct cred *dns_resolver_cache;

/* Checks if supplied name is IP address
* returns:
* 1 - name is IP
Expand Down Expand Up @@ -94,6 +98,7 @@ struct key_type key_type_dns_resolver = {
int
dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
{
const struct cred *saved_cred;
int rc = -EAGAIN;
struct key *rkey = ERR_PTR(-EAGAIN);
char *name;
Expand Down Expand Up @@ -133,8 +138,15 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
goto skip_upcall;
}

saved_cred = override_creds(dns_resolver_cache);
rkey = request_key(&key_type_dns_resolver, name, "");
revert_creds(saved_cred);
if (!IS_ERR(rkey)) {
if (!(rkey->perm & KEY_USR_VIEW)) {
down_read(&rkey->sem);
rkey->perm |= KEY_USR_VIEW;
up_read(&rkey->sem);
}
len = rkey->type_data.x[0];
data = rkey->payload.data;
} else {
Expand Down Expand Up @@ -165,4 +177,61 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
return rc;
}

int __init cifs_init_dns_resolver(void)
{
struct cred *cred;
struct key *keyring;
int ret;

printk(KERN_NOTICE "Registering the %s key type\n",
key_type_dns_resolver.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, ".dns_resolver", 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(&key_type_dns_resolver);
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;
dns_resolver_cache = cred;
return 0;

failed_put_key:
key_put(keyring);
failed_put_cred:
put_cred(cred);
return ret;
}

void __exit cifs_exit_dns_resolver(void)
{
key_revoke(dns_resolver_cache->thread_keyring);
unregister_key_type(&key_type_dns_resolver);
put_cred(dns_resolver_cache);
printk(KERN_NOTICE "Unregistered %s key type\n",
key_type_dns_resolver.name);
}
4 changes: 2 additions & 2 deletions trunk/fs/cifs/dns_resolve.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
#define _DNS_RESOLVE_H

#ifdef __KERNEL__
#include <linux/key-type.h>
extern struct key_type key_type_dns_resolver;
extern int __init cifs_init_dns_resolver(void);
extern void __exit cifs_exit_dns_resolver(void);
extern int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr);
#endif /* KERNEL */

Expand Down

0 comments on commit 2d01b5c

Please sign in to comment.