diff --git a/[refs] b/[refs] index 53f733ab79c1..d0b6d909a76c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7ab501db8cb6659efdf04034e0de6b44c059a51b +refs/heads/master: 2256c13b992b09f1f9563c26457aa048da2865df diff --git a/trunk/Documentation/keys-request-key.txt b/trunk/Documentation/keys-request-key.txt deleted file mode 100644 index 5f2b9c5edbb5..000000000000 --- a/trunk/Documentation/keys-request-key.txt +++ /dev/null @@ -1,161 +0,0 @@ - =================== - KEY REQUEST SERVICE - =================== - -The key request service is part of the key retention service (refer to -Documentation/keys.txt). This document explains more fully how that the -requesting algorithm works. - -The process starts by either the kernel requesting a service by calling -request_key(): - - struct key *request_key(const struct key_type *type, - const char *description, - const char *callout_string); - -Or by userspace invoking the request_key system call: - - key_serial_t request_key(const char *type, - const char *description, - const char *callout_info, - key_serial_t dest_keyring); - -The main difference between the two access points is that the in-kernel -interface does not need to link the key to a keyring to prevent it from being -immediately destroyed. The kernel interface returns a pointer directly to the -key, and it's up to the caller to destroy the key. - -The userspace interface links the key to a keyring associated with the process -to prevent the key from going away, and returns the serial number of the key to -the caller. - - -=========== -THE PROCESS -=========== - -A request proceeds in the following manner: - - (1) Process A calls request_key() [the userspace syscall calls the kernel - interface]. - - (2) request_key() searches the process's subscribed keyrings to see if there's - a suitable key there. If there is, it returns the key. If there isn't, and - callout_info is not set, an error is returned. Otherwise the process - proceeds to the next step. - - (3) request_key() sees that A doesn't have the desired key yet, so it creates - two things: - - (a) An uninstantiated key U of requested type and description. - - (b) An authorisation key V that refers to key U and notes that process A - is the context in which key U should be instantiated and secured, and - from which associated key requests may be satisfied. - - (4) request_key() then forks and executes /sbin/request-key with a new session - keyring that contains a link to auth key V. - - (5) /sbin/request-key execs an appropriate program to perform the actual - instantiation. - - (6) The program may want to access another key from A's context (say a - Kerberos TGT key). It just requests the appropriate key, and the keyring - search notes that the session keyring has auth key V in its bottom level. - - This will permit it to then search the keyrings of process A with the - UID, GID, groups and security info of process A as if it was process A, - and come up with key W. - - (7) The program then does what it must to get the data with which to - instantiate key U, using key W as a reference (perhaps it contacts a - Kerberos server using the TGT) and then instantiates key U. - - (8) Upon instantiating key U, auth key V is automatically revoked so that it - may not be used again. - - (9) The program then exits 0 and request_key() deletes key V and returns key - U to the caller. - -This also extends further. If key W (step 5 above) didn't exist, key W would be -created uninstantiated, another auth key (X) would be created [as per step 3] -and another copy of /sbin/request-key spawned [as per step 4]; but the context -specified by auth key X will still be process A, as it was in auth key V. - -This is because process A's keyrings can't simply be attached to -/sbin/request-key at the appropriate places because (a) execve will discard two -of them, and (b) it requires the same UID/GID/Groups all the way through. - - -====================== -NEGATIVE INSTANTIATION -====================== - -Rather than instantiating a key, it is possible for the possessor of an -authorisation key to negatively instantiate a key that's under construction. -This is a short duration placeholder that causes any attempt at re-requesting -the key whilst it exists to fail with error ENOKEY. - -This is provided to prevent excessive repeated spawning of /sbin/request-key -processes for a key that will never be obtainable. - -Should the /sbin/request-key process exit anything other than 0 or die on a -signal, the key under construction will be automatically negatively -instantiated for a short amount of time. - - -==================== -THE SEARCH ALGORITHM -==================== - -A search of any particular keyring proceeds in the following fashion: - - (1) When the key management code searches for a key (keyring_search_aux) it - firstly calls key_permission(SEARCH) on the keyring it's starting with, - if this denies permission, it doesn't search further. - - (2) It considers all the non-keyring keys within that keyring and, if any key - matches the criteria specified, calls key_permission(SEARCH) on it to see - if the key is allowed to be found. If it is, that key is returned; if - not, the search continues, and the error code is retained if of higher - priority than the one currently set. - - (3) It then considers all the keyring-type keys in the keyring it's currently - searching. It calls key_permission(SEARCH) on each keyring, and if this - grants permission, it recurses, executing steps (2) and (3) on that - keyring. - -The process stops immediately a valid key is found with permission granted to -use it. Any error from a previous match attempt is discarded and the key is -returned. - -When search_process_keyrings() is invoked, it performs the following searches -until one succeeds: - - (1) If extant, the process's thread keyring is searched. - - (2) If extant, the process's process keyring is searched. - - (3) The process's session keyring is searched. - - (4) If the process has a request_key() authorisation key in its session - keyring then: - - (a) If extant, the calling process's thread keyring is searched. - - (b) If extant, the calling process's process keyring is searched. - - (c) The calling process's session keyring is searched. - -The moment one succeeds, all pending errors are discarded and the found key is -returned. - -Only if all these fail does the whole thing fail with the highest priority -error. Note that several errors may have come from LSM. - -The error priority is: - - EKEYREVOKED > EKEYEXPIRED > ENOKEY - -EACCES/EPERM are only returned on a direct search of a specific keyring where -the basal keyring does not grant Search permission. diff --git a/trunk/Documentation/keys.txt b/trunk/Documentation/keys.txt index 4afe03a58c5b..b22e7c8d059a 100644 --- a/trunk/Documentation/keys.txt +++ b/trunk/Documentation/keys.txt @@ -361,8 +361,6 @@ The main syscalls are: /sbin/request-key will be invoked in an attempt to obtain a key. The callout_info string will be passed as an argument to the program. - See also Documentation/keys-request-key.txt. - The keyctl syscall functions are: @@ -535,8 +533,8 @@ The keyctl syscall functions are: (*) Read the payload data from a key: - long keyctl(KEYCTL_READ, key_serial_t keyring, char *buffer, - size_t buflen); + key_serial_t keyctl(KEYCTL_READ, key_serial_t keyring, char *buffer, + size_t buflen); This function attempts to read the payload data from the specified key into the buffer. The process must have read permission on the key to @@ -557,9 +555,9 @@ The keyctl syscall functions are: (*) Instantiate a partially constructed key. - long keyctl(KEYCTL_INSTANTIATE, key_serial_t key, - const void *payload, size_t plen, - key_serial_t keyring); + key_serial_t keyctl(KEYCTL_INSTANTIATE, key_serial_t key, + const void *payload, size_t plen, + key_serial_t keyring); If the kernel calls back to userspace to complete the instantiation of a key, userspace should use this call to supply data for the key before the @@ -578,8 +576,8 @@ The keyctl syscall functions are: (*) Negatively instantiate a partially constructed key. - long keyctl(KEYCTL_NEGATE, key_serial_t key, - unsigned timeout, key_serial_t keyring); + key_serial_t keyctl(KEYCTL_NEGATE, key_serial_t key, + unsigned timeout, key_serial_t keyring); If the kernel calls back to userspace to complete the instantiation of a key, userspace should use this call mark the key as negative before the @@ -690,8 +688,6 @@ payload contents" for more information. If successful, the key will have been attached to the default keyring for implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING. - See also Documentation/keys-request-key.txt. - (*) When it is no longer required, the key should be released using: diff --git a/trunk/arch/sparc64/kernel/power.c b/trunk/arch/sparc64/kernel/power.c index 946cee0257ea..9e8362ea3104 100644 --- a/trunk/arch/sparc64/kernel/power.c +++ b/trunk/arch/sparc64/kernel/power.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -100,46 +101,83 @@ static int powerd(void *__unused) return 0; } -static int __init has_button_interrupt(struct linux_ebus_device *edev) +static int __init has_button_interrupt(unsigned int irq, int prom_node) { - if (edev->irqs[0] == PCI_IRQ_NONE) + if (irq == PCI_IRQ_NONE) return 0; - if (!prom_node_has_property(edev->prom_node, "button")) + if (!prom_node_has_property(prom_node, "button")) return 0; return 1; } -void __init power_init(void) +static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p) { struct linux_ebus *ebus; struct linux_ebus_device *edev; + + for_each_ebus(ebus) { + for_each_ebusdev(edev, ebus) { + if (!strcmp(edev->prom_name, "power")) { + *resp = &edev->resource[0]; + *irq_p = edev->irqs[0]; + *prom_node_p = edev->prom_node; + return 0; + } + } + } + return -ENODEV; +} + +static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p) +{ + struct sparc_isa_bridge *isa_bus; + struct sparc_isa_device *isa_dev; + + for_each_isa(isa_bus) { + for_each_isadev(isa_dev, isa_bus) { + if (!strcmp(isa_dev->prom_name, "power")) { + *resp = &isa_dev->resource; + *irq_p = isa_dev->irq; + *prom_node_p = isa_dev->prom_node; + return 0; + } + } + } + return -ENODEV; +} + +void __init power_init(void) +{ + struct resource *res = NULL; + unsigned int irq; + int prom_node; static int invoked; if (invoked) return; invoked = 1; - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "power")) - goto found; - } - } + if (!power_probe_ebus(&res, &irq, &prom_node)) + goto found; + + if (!power_probe_isa(&res, &irq, &prom_node)) + goto found; + return; found: - power_reg = ioremap(edev->resource[0].start, 0x4); + power_reg = ioremap(res->start, 0x4); printk("power: Control reg at %p ... ", power_reg); poweroff_method = machine_halt; /* able to use the standard halt */ - if (has_button_interrupt(edev)) { + if (has_button_interrupt(irq, prom_node)) { if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { printk("Failed to start power daemon.\n"); return; } printk("powerd running.\n"); - if (request_irq(edev->irqs[0], + if (request_irq(irq, power_handler, SA_SHIRQ, "power", NULL) < 0) printk("power: Error, cannot register IRQ handler.\n"); } else { diff --git a/trunk/drivers/pcmcia/ti113x.h b/trunk/drivers/pcmcia/ti113x.h index 539b5cd1a598..da0b404561c9 100644 --- a/trunk/drivers/pcmcia/ti113x.h +++ b/trunk/drivers/pcmcia/ti113x.h @@ -873,7 +873,6 @@ static int ti1250_override(struct yenta_socket *socket) * Some fixup code to make everybody happy (TM). */ -#ifdef CONFIG_CARDBUS /** * set/clear various test bits: * Defaults to clear the bit. @@ -928,6 +927,7 @@ static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus) config_writeb(socket, ENE_TEST_C9, test_c9); } + static int ene_override(struct yenta_socket *socket) { /* install tune_bridge() function */ @@ -935,9 +935,6 @@ static int ene_override(struct yenta_socket *socket) return ti1250_override(socket); } -#else -# define ene_override ti1250_override -#endif #endif /* _LINUX_TI113X_H */ diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index aa62dbda93ac..043d587216b5 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -1551,19 +1551,19 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) if (nd->last_type != LAST_NORM) goto exit; if (nd->last.name[nd->last.len]) { - __putname(nd->last.name); + putname(nd->last.name); goto exit; } error = -ELOOP; if (count++==32) { - __putname(nd->last.name); + putname(nd->last.name); goto exit; } dir = nd->dentry; down(&dir->d_inode->i_sem); path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); path.mnt = nd->mnt; - __putname(nd->last.name); + putname(nd->last.name); goto do_last; } diff --git a/trunk/include/linux/key-ui.h b/trunk/include/linux/key-ui.h index 7a2e332067c3..918c34a8347e 100644 --- a/trunk/include/linux/key-ui.h +++ b/trunk/include/linux/key-ui.h @@ -38,16 +38,97 @@ struct keyring_list { struct key *keys[0]; }; + /* * check to see whether permission is granted to use a key in the desired way */ -extern int key_task_permission(const key_ref_t key_ref, - struct task_struct *context, - key_perm_t perm); - static inline int key_permission(const key_ref_t key_ref, key_perm_t perm) { - return key_task_permission(key_ref, current, perm); + struct key *key = key_ref_to_ptr(key_ref); + key_perm_t kperm; + + if (is_key_possessed(key_ref)) + kperm = key->perm >> 24; + else if (key->uid == current->fsuid) + kperm = key->perm >> 16; + else if (key->gid != -1 && + key->perm & KEY_GRP_ALL && + in_group_p(key->gid) + ) + kperm = key->perm >> 8; + else + kperm = key->perm; + + kperm = kperm & perm & KEY_ALL; + + return kperm == perm; +} + +/* + * check to see whether permission is granted to use a key in at least one of + * the desired ways + */ +static inline int key_any_permission(const key_ref_t key_ref, key_perm_t perm) +{ + struct key *key = key_ref_to_ptr(key_ref); + key_perm_t kperm; + + if (is_key_possessed(key_ref)) + kperm = key->perm >> 24; + else if (key->uid == current->fsuid) + kperm = key->perm >> 16; + else if (key->gid != -1 && + key->perm & KEY_GRP_ALL && + in_group_p(key->gid) + ) + kperm = key->perm >> 8; + else + kperm = key->perm; + + kperm = kperm & perm & KEY_ALL; + + return kperm != 0; +} + +static inline int key_task_groups_search(struct task_struct *tsk, gid_t gid) +{ + int ret; + + task_lock(tsk); + ret = groups_search(tsk->group_info, gid); + task_unlock(tsk); + return ret; +} + +static inline int key_task_permission(const key_ref_t key_ref, + struct task_struct *context, + key_perm_t perm) +{ + struct key *key = key_ref_to_ptr(key_ref); + key_perm_t kperm; + + if (is_key_possessed(key_ref)) { + kperm = key->perm >> 24; + } + else if (key->uid == context->fsuid) { + kperm = key->perm >> 16; + } + else if (key->gid != -1 && + key->perm & KEY_GRP_ALL && ( + key->gid == context->fsgid || + key_task_groups_search(context, key->gid) + ) + ) { + kperm = key->perm >> 8; + } + else { + kperm = key->perm; + } + + kperm = kperm & perm & KEY_ALL; + + return kperm == perm; + } extern key_ref_t lookup_user_key(struct task_struct *context, diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index c135f5aa2c2d..619b027e92b5 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -578,8 +578,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) * is to alert stop-signal processing code when another * processor has come along and cleared the flag. */ - if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) - tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; + tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; } if ( signr && ((info->si_code & __SI_MASK) == __SI_TIMER) && diff --git a/trunk/security/keys/Makefile b/trunk/security/keys/Makefile index 5145adfb6a05..c392d750b208 100644 --- a/trunk/security/keys/Makefile +++ b/trunk/security/keys/Makefile @@ -6,7 +6,6 @@ obj-y := \ key.o \ keyring.o \ keyctl.o \ - permission.o \ process_keys.o \ request_key.o \ request_key_auth.o \ diff --git a/trunk/security/keys/permission.c b/trunk/security/keys/permission.c deleted file mode 100644 index 03db073ba45c..000000000000 --- a/trunk/security/keys/permission.c +++ /dev/null @@ -1,70 +0,0 @@ -/* permission.c: key permission determination - * - * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include "internal.h" - -/*****************************************************************************/ -/* - * check to see whether permission is granted to use a key in the desired way, - * but permit the security modules to override - */ -int key_task_permission(const key_ref_t key_ref, - struct task_struct *context, - key_perm_t perm) -{ - struct key *key; - key_perm_t kperm; - int ret; - - key = key_ref_to_ptr(key_ref); - - /* use the second 8-bits of permissions for keys the caller owns */ - if (key->uid == context->fsuid) { - kperm = key->perm >> 16; - goto use_these_perms; - } - - /* use the third 8-bits of permissions for keys the caller has a group - * membership in common with */ - if (key->gid != -1 && key->perm & KEY_GRP_ALL) { - if (key->gid == context->fsgid) { - kperm = key->perm >> 8; - goto use_these_perms; - } - - task_lock(context); - ret = groups_search(context->group_info, key->gid); - task_unlock(context); - - if (ret) { - kperm = key->perm >> 8; - goto use_these_perms; - } - } - - /* otherwise use the least-significant 8-bits */ - kperm = key->perm; - -use_these_perms: - /* use the top 8-bits of permissions for keys the caller possesses - * - possessor permissions are additive with other permissions - */ - if (is_key_possessed(key_ref)) - kperm |= key->perm >> 24; - - kperm = kperm & perm & KEY_ALL; - - return kperm == perm; - -} /* end key_task_permission() */ - -EXPORT_SYMBOL(key_task_permission); diff --git a/trunk/security/keys/request_key.c b/trunk/security/keys/request_key.c index 5cc4bba70db6..e6dd366d43a3 100644 --- a/trunk/security/keys/request_key.c +++ b/trunk/security/keys/request_key.c @@ -7,8 +7,6 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. - * - * See Documentation/keys-request-key.txt */ #include diff --git a/trunk/security/keys/request_key_auth.c b/trunk/security/keys/request_key_auth.c index a8e4069d48cb..1ecd3d3fa9f8 100644 --- a/trunk/security/keys/request_key_auth.c +++ b/trunk/security/keys/request_key_auth.c @@ -7,8 +7,6 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. - * - * See Documentation/keys-request-key.txt */ #include @@ -98,7 +96,6 @@ static void request_key_auth_destroy(struct key *key) kenter("{%d}", key->serial); key_put(rka->target_key); - kfree(rka); } /* end request_key_auth_destroy() */