aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/keys-request-key.txt161
-rw-r--r--Documentation/keys.txt18
-rw-r--r--arch/sparc/Kconfig4
-rw-r--r--arch/sparc/defconfig1
-rw-r--r--arch/sparc64/kernel/entry.S39
-rw-r--r--arch/sparc64/kernel/power.c64
-rw-r--r--arch/sparc64/kernel/rtrap.S7
-rw-r--r--arch/sparc64/lib/VISsave.S8
-rw-r--r--drivers/pcmcia/ti113x.h5
-rw-r--r--drivers/video/p9100.c4
-rw-r--r--fs/namei.c6
-rw-r--r--include/linux/key-ui.h91
-rw-r--r--kernel/signal.c3
-rw-r--r--security/keys/Makefile1
-rw-r--r--security/keys/permission.c70
-rw-r--r--security/keys/request_key.c2
-rw-r--r--security/keys/request_key_auth.c3
17 files changed, 352 insertions, 135 deletions
diff --git a/Documentation/keys-request-key.txt b/Documentation/keys-request-key.txt
new file mode 100644
index 000000000000..5f2b9c5edbb5
--- /dev/null
+++ b/Documentation/keys-request-key.txt
@@ -0,0 +1,161 @@
+ ===================
+ 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/Documentation/keys.txt b/Documentation/keys.txt
index b22e7c8d059a..4afe03a58c5b 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -361,6 +361,8 @@ 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:
@@ -533,8 +535,8 @@ The keyctl syscall functions are:
(*) Read the payload data from a key:
- key_serial_t keyctl(KEYCTL_READ, key_serial_t keyring, char *buffer,
- size_t buflen);
+ long 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
@@ -555,9 +557,9 @@ The keyctl syscall functions are:
(*) Instantiate a partially constructed key.
- key_serial_t keyctl(KEYCTL_INSTANTIATE, key_serial_t key,
- const void *payload, size_t plen,
- key_serial_t keyring);
+ long 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
@@ -576,8 +578,8 @@ The keyctl syscall functions are:
(*) Negatively instantiate a partially constructed key.
- key_serial_t keyctl(KEYCTL_NEGATE, key_serial_t key,
- unsigned timeout, key_serial_t keyring);
+ long 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
@@ -688,6 +690,8 @@ 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/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 6537445dac0e..f7c51b869049 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -21,6 +21,10 @@ config GENERIC_ISA_DMA
bool
default y
+config GENERIC_IOMAP
+ bool
+ default y
+
source "init/Kconfig"
menu "General machine setup"
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
index a69856263009..8a3aef1e22f5 100644
--- a/arch/sparc/defconfig
+++ b/arch/sparc/defconfig
@@ -5,6 +5,7 @@ CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_HIGHMEM=y
CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index f685035dbdb8..11a848402fb1 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -33,7 +33,7 @@
/* This is trivial with the new code... */
.globl do_fpdis
do_fpdis:
- sethi %hi(TSTATE_PEF), %g4 ! IEU0
+ sethi %hi(TSTATE_PEF), %g4
rdpr %tstate, %g5
andcc %g5, %g4, %g0
be,pt %xcc, 1f
@@ -50,18 +50,18 @@ do_fpdis:
add %g0, %g0, %g0
ba,a,pt %xcc, rtrap_clr_l6
-1: ldub [%g6 + TI_FPSAVED], %g5 ! Load Group
- wr %g0, FPRS_FEF, %fprs ! LSU Group+4bubbles
- andcc %g5, FPRS_FEF, %g0 ! IEU1 Group
- be,a,pt %icc, 1f ! CTI
- clr %g7 ! IEU0
- ldx [%g6 + TI_GSR], %g7 ! Load Group
-1: andcc %g5, FPRS_DL, %g0 ! IEU1
- bne,pn %icc, 2f ! CTI
- fzero %f0 ! FPA
- andcc %g5, FPRS_DU, %g0 ! IEU1 Group
- bne,pn %icc, 1f ! CTI
- fzero %f2 ! FPA
+1: ldub [%g6 + TI_FPSAVED], %g5
+ wr %g0, FPRS_FEF, %fprs
+ andcc %g5, FPRS_FEF, %g0
+ be,a,pt %icc, 1f
+ clr %g7
+ ldx [%g6 + TI_GSR], %g7
+1: andcc %g5, FPRS_DL, %g0
+ bne,pn %icc, 2f
+ fzero %f0
+ andcc %g5, FPRS_DU, %g0
+ bne,pn %icc, 1f
+ fzero %f2
faddd %f0, %f2, %f4
fmuld %f0, %f2, %f6
faddd %f0, %f2, %f8
@@ -104,8 +104,10 @@ do_fpdis:
add %g6, TI_FPREGS + 0xc0, %g2
faddd %f0, %f2, %f8
fmuld %f0, %f2, %f10
- ldda [%g1] ASI_BLK_S, %f32 ! grrr, where is ASI_BLK_NUCLEUS 8-(
+ membar #Sync
+ ldda [%g1] ASI_BLK_S, %f32
ldda [%g2] ASI_BLK_S, %f48
+ membar #Sync
faddd %f0, %f2, %f12
fmuld %f0, %f2, %f14
faddd %f0, %f2, %f16
@@ -116,7 +118,6 @@ do_fpdis:
fmuld %f0, %f2, %f26
faddd %f0, %f2, %f28
fmuld %f0, %f2, %f30
- membar #Sync
b,pt %xcc, fpdis_exit
nop
2: andcc %g5, FPRS_DU, %g0
@@ -133,8 +134,10 @@ do_fpdis:
add %g6, TI_FPREGS + 0x40, %g2
faddd %f32, %f34, %f36
fmuld %f32, %f34, %f38
- ldda [%g1] ASI_BLK_S, %f0 ! grrr, where is ASI_BLK_NUCLEUS 8-(
+ membar #Sync
+ ldda [%g1] ASI_BLK_S, %f0
ldda [%g2] ASI_BLK_S, %f16
+ membar #Sync
faddd %f32, %f34, %f40
fmuld %f32, %f34, %f42
faddd %f32, %f34, %f44
@@ -147,7 +150,6 @@ do_fpdis:
fmuld %f32, %f34, %f58
faddd %f32, %f34, %f60
fmuld %f32, %f34, %f62
- membar #Sync
ba,pt %xcc, fpdis_exit
nop
3: mov SECONDARY_CONTEXT, %g3
@@ -158,7 +160,8 @@ do_fpdis:
stxa %g2, [%g3] ASI_DMMU
membar #Sync
mov 0x40, %g2
- ldda [%g1] ASI_BLK_S, %f0 ! grrr, where is ASI_BLK_NUCLEUS 8-(
+ membar #Sync
+ ldda [%g1] ASI_BLK_S, %f0
ldda [%g1 + %g2] ASI_BLK_S, %f16
add %g1, 0x80, %g1
ldda [%g1] ASI_BLK_S, %f32
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 946cee0257ea..9e8362ea3104 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -17,6 +17,7 @@
#include <asm/system.h>
#include <asm/ebus.h>
+#include <asm/isa.h>
#include <asm/auxio.h>
#include <linux/unistd.h>
@@ -100,46 +101,83 @@ again:
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/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index ecfb42a69a44..090dcca00d2a 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -312,32 +312,33 @@ kern_fpucheck: ldub [%g6 + TI_FPDEPTH], %l5
wr %g1, FPRS_FEF, %fprs
ldx [%o1 + %o5], %g1
add %g6, TI_XFSR, %o1
- membar #StoreLoad | #LoadLoad
sll %o0, 8, %o2
add %g6, TI_FPREGS, %o3
brz,pn %l6, 1f
add %g6, TI_FPREGS+0x40, %o4
+ membar #Sync
ldda [%o3 + %o2] ASI_BLK_P, %f0
ldda [%o4 + %o2] ASI_BLK_P, %f16
+ membar #Sync
1: andcc %l2, FPRS_DU, %g0
be,pn %icc, 1f
wr %g1, 0, %gsr
add %o2, 0x80, %o2
+ membar #Sync
ldda [%o3 + %o2] ASI_BLK_P, %f32
ldda [%o4 + %o2] ASI_BLK_P, %f48
-
1: membar #Sync
ldx [%o1 + %o5], %fsr
2: stb %l5, [%g6 + TI_FPDEPTH]
ba,pt %xcc, rt_continue
nop
5: wr %g0, FPRS_FEF, %fprs
- membar #StoreLoad | #LoadLoad
sll %o0, 8, %o2
add %g6, TI_FPREGS+0x80, %o3
add %g6, TI_FPREGS+0xc0, %o4
+ membar #Sync
ldda [%o3 + %o2] ASI_BLK_P, %f32
ldda [%o4 + %o2] ASI_BLK_P, %f48
membar #Sync
diff --git a/arch/sparc64/lib/VISsave.S b/arch/sparc64/lib/VISsave.S
index 4e18989bd602..a0ded5c5aa5c 100644
--- a/arch/sparc64/lib/VISsave.S
+++ b/arch/sparc64/lib/VISsave.S
@@ -59,15 +59,17 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3
be,pn %icc, 9b
add %g6, TI_FPREGS, %g2
andcc %o5, FPRS_DL, %g0
- membar #StoreStore | #LoadStore
be,pn %icc, 4f
add %g6, TI_FPREGS+0x40, %g3
+ membar #Sync
stda %f0, [%g2 + %g1] ASI_BLK_P
stda %f16, [%g3 + %g1] ASI_BLK_P
+ membar #Sync
andcc %o5, FPRS_DU, %g0
be,pn %icc, 5f
4: add %g1, 128, %g1
+ membar #Sync
stda %f32, [%g2 + %g1] ASI_BLK_P
stda %f48, [%g3 + %g1] ASI_BLK_P
@@ -87,7 +89,7 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3
sll %g1, 5, %g1
add %g6, TI_FPREGS+0xc0, %g3
wr %g0, FPRS_FEF, %fprs
- membar #StoreStore | #LoadStore
+ membar #Sync
stda %f32, [%g2 + %g1] ASI_BLK_P
stda %f48, [%g3 + %g1] ASI_BLK_P
membar #Sync
@@ -128,8 +130,8 @@ VISenterhalf:
be,pn %icc, 4f
add %g6, TI_FPREGS, %g2
- membar #StoreStore | #LoadStore
add %g6, TI_FPREGS+0x40, %g3
+ membar #Sync
stda %f0, [%g2 + %g1] ASI_BLK_P
stda %f16, [%g3 + %g1] ASI_BLK_P
membar #Sync
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index da0b404561c9..539b5cd1a598 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -873,6 +873,7 @@ 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.
@@ -927,7 +928,6 @@ 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,6 +935,9 @@ 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/drivers/video/p9100.c b/drivers/video/p9100.c
index 7808a01493ad..b76a5a9a125b 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -288,6 +288,9 @@ static void p9100_init_one(struct sbus_dev *sdev)
all->par.physbase = sdev->reg_addrs[2].phys_addr;
sbusfb_fill_var(&all->info.var, sdev->prom_node, 8);
+ all->info.var.red.length = 8;
+ all->info.var.green.length = 8;
+ all->info.var.blue.length = 8;
linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
all->info.var.xres);
@@ -323,6 +326,7 @@ static void p9100_init_one(struct sbus_dev *sdev)
kfree(all);
return;
}
+ fb_set_cmap(&all->info.cmap, &all->info);
list_add(&all->list, &p9100_list);
diff --git a/fs/namei.c b/fs/namei.c
index 043d587216b5..aa62dbda93ac 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1551,19 +1551,19 @@ do_link:
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/include/linux/key-ui.h b/include/linux/key-ui.h
index 918c34a8347e..7a2e332067c3 100644
--- a/include/linux/key-ui.h
+++ b/include/linux/key-ui.h
@@ -38,97 +38,16 @@ struct keyring_list {
struct key *keys[0];
};
-
/*
* check to see whether permission is granted to use a key in the desired way
*/
-static inline int key_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 == 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;
+extern int key_task_permission(const key_ref_t key_ref,
+ struct task_struct *context,
+ key_perm_t 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)
+static inline int key_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 == 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;
-
+ return key_task_permission(key_ref, current, perm);
}
extern key_ref_t lookup_user_key(struct task_struct *context,
diff --git a/kernel/signal.c b/kernel/signal.c
index 619b027e92b5..c135f5aa2c2d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -578,7 +578,8 @@ 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.
*/
- tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
+ if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
+ tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
}
if ( signr &&
((info->si_code & __SI_MASK) == __SI_TIMER) &&
diff --git a/security/keys/Makefile b/security/keys/Makefile
index c392d750b208..5145adfb6a05 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -6,6 +6,7 @@ obj-y := \
key.o \
keyring.o \
keyctl.o \
+ permission.o \
process_keys.o \
request_key.o \
request_key_auth.o \
diff --git a/security/keys/permission.c b/security/keys/permission.c
new file mode 100644
index 000000000000..03db073ba45c
--- /dev/null
+++ b/security/keys/permission.c
@@ -0,0 +1,70 @@
+/* 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 <linux/module.h>
+#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/security/keys/request_key.c b/security/keys/request_key.c
index e6dd366d43a3..5cc4bba70db6 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -7,6 +7,8 @@
* 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 <linux/module.h>
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 1ecd3d3fa9f8..a8e4069d48cb 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -7,6 +7,8 @@
* 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 <linux/module.h>
@@ -96,6 +98,7 @@ 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() */