From 9c61123da058f111b4ec80d8320fbd10171bc9c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Skytte=20J=F8rgensen?= Date: Thu, 6 Oct 2005 21:36:17 -0700 Subject: [PATCH] --- yaml --- r: 9723 b: refs/heads/master c: 5fe467ee9787007dd9b263eb42dde3742deb743b h: refs/heads/master i: 9721: ee2765cb7a08d19fc928853bfe22a3702a966465 9719: 6bdcb514d4e858bf522d366f26c89fe7aceed846 v: v3 --- [refs] | 2 +- trunk/Documentation/keys-request-key.txt | 161 --------------- trunk/Documentation/keys.txt | 18 +- trunk/arch/sparc/Kconfig | 4 - trunk/arch/sparc/defconfig | 1 - trunk/arch/sparc64/kernel/entry.S | 39 ++-- trunk/arch/sparc64/kernel/power.c | 64 ++---- trunk/arch/sparc64/kernel/rtrap.S | 7 +- trunk/arch/sparc64/lib/VISsave.S | 8 +- trunk/drivers/pcmcia/ti113x.h | 5 +- trunk/drivers/video/p9100.c | 4 - trunk/fs/namei.c | 6 +- trunk/include/linux/key-ui.h | 91 +++++++- trunk/include/net/sctp/user.h | 23 ++- trunk/kernel/signal.c | 3 +- trunk/net/sctp/socket.c | 252 ++++++++++++++++++++--- trunk/security/keys/Makefile | 1 - trunk/security/keys/permission.c | 70 ------- trunk/security/keys/request_key.c | 2 - trunk/security/keys/request_key_auth.c | 3 - 20 files changed, 379 insertions(+), 385 deletions(-) delete mode 100644 trunk/Documentation/keys-request-key.txt delete mode 100644 trunk/security/keys/permission.c diff --git a/[refs] b/[refs] index 5d9e9a98c3d8..e47940d00746 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 582fd487611baa06b07665978429192390c29b8f +refs/heads/master: 5fe467ee9787007dd9b263eb42dde3742deb743b 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/sparc/Kconfig b/trunk/arch/sparc/Kconfig index f7c51b869049..6537445dac0e 100644 --- a/trunk/arch/sparc/Kconfig +++ b/trunk/arch/sparc/Kconfig @@ -21,10 +21,6 @@ config GENERIC_ISA_DMA bool default y -config GENERIC_IOMAP - bool - default y - source "init/Kconfig" menu "General machine setup" diff --git a/trunk/arch/sparc/defconfig b/trunk/arch/sparc/defconfig index 8a3aef1e22f5..a69856263009 100644 --- a/trunk/arch/sparc/defconfig +++ b/trunk/arch/sparc/defconfig @@ -5,7 +5,6 @@ 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/trunk/arch/sparc64/kernel/entry.S b/trunk/arch/sparc64/kernel/entry.S index 11a848402fb1..f685035dbdb8 100644 --- a/trunk/arch/sparc64/kernel/entry.S +++ b/trunk/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 + sethi %hi(TSTATE_PEF), %g4 ! IEU0 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 - 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 +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 faddd %f0, %f2, %f4 fmuld %f0, %f2, %f6 faddd %f0, %f2, %f8 @@ -104,10 +104,8 @@ do_fpdis: add %g6, TI_FPREGS + 0xc0, %g2 faddd %f0, %f2, %f8 fmuld %f0, %f2, %f10 - membar #Sync - ldda [%g1] ASI_BLK_S, %f32 + ldda [%g1] ASI_BLK_S, %f32 ! grrr, where is ASI_BLK_NUCLEUS 8-( ldda [%g2] ASI_BLK_S, %f48 - membar #Sync faddd %f0, %f2, %f12 fmuld %f0, %f2, %f14 faddd %f0, %f2, %f16 @@ -118,6 +116,7 @@ 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 @@ -134,10 +133,8 @@ do_fpdis: add %g6, TI_FPREGS + 0x40, %g2 faddd %f32, %f34, %f36 fmuld %f32, %f34, %f38 - membar #Sync - ldda [%g1] ASI_BLK_S, %f0 + ldda [%g1] ASI_BLK_S, %f0 ! grrr, where is ASI_BLK_NUCLEUS 8-( ldda [%g2] ASI_BLK_S, %f16 - membar #Sync faddd %f32, %f34, %f40 fmuld %f32, %f34, %f42 faddd %f32, %f34, %f44 @@ -150,6 +147,7 @@ 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 @@ -160,8 +158,7 @@ do_fpdis: stxa %g2, [%g3] ASI_DMMU membar #Sync mov 0x40, %g2 - membar #Sync - ldda [%g1] ASI_BLK_S, %f0 + ldda [%g1] ASI_BLK_S, %f0 ! grrr, where is ASI_BLK_NUCLEUS 8-( ldda [%g1 + %g2] ASI_BLK_S, %f16 add %g1, 0x80, %g1 ldda [%g1] ASI_BLK_S, %f32 diff --git a/trunk/arch/sparc64/kernel/power.c b/trunk/arch/sparc64/kernel/power.c index 9e8362ea3104..946cee0257ea 100644 --- a/trunk/arch/sparc64/kernel/power.c +++ b/trunk/arch/sparc64/kernel/power.c @@ -17,7 +17,6 @@ #include #include -#include #include #include @@ -101,83 +100,46 @@ static int powerd(void *__unused) return 0; } -static int __init has_button_interrupt(unsigned int irq, int prom_node) +static int __init has_button_interrupt(struct linux_ebus_device *edev) { - if (irq == PCI_IRQ_NONE) + if (edev->irqs[0] == PCI_IRQ_NONE) return 0; - if (!prom_node_has_property(prom_node, "button")) + if (!prom_node_has_property(edev->prom_node, "button")) return 0; return 1; } -static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p) +void __init power_init(void) { 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; - if (!power_probe_ebus(&res, &irq, &prom_node)) - goto found; - - if (!power_probe_isa(&res, &irq, &prom_node)) - goto found; - + for_each_ebus(ebus) { + for_each_ebusdev(edev, ebus) { + if (!strcmp(edev->prom_name, "power")) + goto found; + } + } return; found: - power_reg = ioremap(res->start, 0x4); + power_reg = ioremap(edev->resource[0].start, 0x4); printk("power: Control reg at %p ... ", power_reg); poweroff_method = machine_halt; /* able to use the standard halt */ - if (has_button_interrupt(irq, prom_node)) { + if (has_button_interrupt(edev)) { if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { printk("Failed to start power daemon.\n"); return; } printk("powerd running.\n"); - if (request_irq(irq, + if (request_irq(edev->irqs[0], power_handler, SA_SHIRQ, "power", NULL) < 0) printk("power: Error, cannot register IRQ handler.\n"); } else { diff --git a/trunk/arch/sparc64/kernel/rtrap.S b/trunk/arch/sparc64/kernel/rtrap.S index 090dcca00d2a..ecfb42a69a44 100644 --- a/trunk/arch/sparc64/kernel/rtrap.S +++ b/trunk/arch/sparc64/kernel/rtrap.S @@ -312,33 +312,32 @@ 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/trunk/arch/sparc64/lib/VISsave.S b/trunk/arch/sparc64/lib/VISsave.S index a0ded5c5aa5c..4e18989bd602 100644 --- a/trunk/arch/sparc64/lib/VISsave.S +++ b/trunk/arch/sparc64/lib/VISsave.S @@ -59,17 +59,15 @@ 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 @@ -89,7 +87,7 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 sll %g1, 5, %g1 add %g6, TI_FPREGS+0xc0, %g3 wr %g0, FPRS_FEF, %fprs - membar #Sync + membar #StoreStore | #LoadStore stda %f32, [%g2 + %g1] ASI_BLK_P stda %f48, [%g3 + %g1] ASI_BLK_P membar #Sync @@ -130,8 +128,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/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/drivers/video/p9100.c b/trunk/drivers/video/p9100.c index b76a5a9a125b..7808a01493ad 100644 --- a/trunk/drivers/video/p9100.c +++ b/trunk/drivers/video/p9100.c @@ -288,9 +288,6 @@ 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); @@ -326,7 +323,6 @@ 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/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/include/net/sctp/user.h b/trunk/include/net/sctp/user.h index f6328aeddcce..e81ab52755fb 100644 --- a/trunk/include/net/sctp/user.h +++ b/trunk/include/net/sctp/user.h @@ -103,16 +103,20 @@ enum sctp_optname { #define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_PEELOFF, /* peel off association. */ #define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF - SCTP_GET_PEER_ADDRS_NUM, /* Get number of peer addresss. */ -#define SCTP_GET_PEER_ADDRS_NUM SCTP_GET_PEER_ADDRS_NUM + SCTP_GET_PEER_ADDRS_NUM_OLD, /* Get number of peer addresss. */ +#define SCTP_GET_PEER_ADDRS_NUM_OLD SCTP_GET_PEER_ADDRS_NUM_OLD + SCTP_GET_PEER_ADDRS_OLD, /* Get all peer addresss. */ +#define SCTP_GET_PEER_ADDRS_OLD SCTP_GET_PEER_ADDRS_OLD + SCTP_GET_LOCAL_ADDRS_NUM_OLD, /* Get number of local addresss. */ +#define SCTP_GET_LOCAL_ADDRS_NUM_OLD SCTP_GET_LOCAL_ADDRS_NUM_OLD + SCTP_GET_LOCAL_ADDRS_OLD, /* Get all local addresss. */ +#define SCTP_GET_LOCAL_ADDRS_OLD SCTP_GET_LOCAL_ADDRS_OLD + SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */ +#define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX SCTP_GET_PEER_ADDRS, /* Get all peer addresss. */ #define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS - SCTP_GET_LOCAL_ADDRS_NUM, /* Get number of local addresss. */ -#define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS - SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */ -#define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX }; /* @@ -559,11 +563,16 @@ struct sctp_status { * SCTP_GET_LOCAL_ADDRS socket options used internally to implement * sctp_getpaddrs() and sctp_getladdrs() API. */ -struct sctp_getaddrs { +struct sctp_getaddrs_old { sctp_assoc_t assoc_id; int addr_num; struct sockaddr __user *addrs; }; +struct sctp_getaddrs { + sctp_assoc_t assoc_id; /*input*/ + __u32 addr_num; /*output*/ + __u8 addrs[0]; /*output, variable size*/ +}; /* These are bit fields for msghdr->msg_flags. See section 5.1. */ /* On user space Linux, these live in as an enum. */ 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/net/sctp/socket.c b/trunk/net/sctp/socket.c index 91ec8c936913..02e068d3450d 100644 --- a/trunk/net/sctp/socket.c +++ b/trunk/net/sctp/socket.c @@ -3159,8 +3159,9 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval return 0; } -static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, - char __user *optval, int __user *optlen) +static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len, + char __user *optval, + int __user *optlen) { sctp_assoc_t id; struct sctp_association *asoc; @@ -3185,23 +3186,28 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, return cnt; } -static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, - char __user *optval, int __user *optlen) +/* + * Old API for getting list of peer addresses. Does not work for 32-bit + * programs running on a 64-bit kernel + */ +static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len, + char __user *optval, + int __user *optlen) { struct sctp_association *asoc; struct list_head *pos; int cnt = 0; - struct sctp_getaddrs getaddrs; + struct sctp_getaddrs_old getaddrs; struct sctp_transport *from; void __user *to; union sctp_addr temp; struct sctp_sock *sp = sctp_sk(sk); int addrlen; - if (len != sizeof(struct sctp_getaddrs)) + if (len != sizeof(struct sctp_getaddrs_old)) return -EINVAL; - if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) + if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old))) return -EFAULT; if (getaddrs.addr_num <= 0) return -EINVAL; @@ -3225,15 +3231,69 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, if (cnt >= getaddrs.addr_num) break; } getaddrs.addr_num = cnt; - if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs))) + if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old))) + return -EFAULT; + + return 0; +} + +static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, + char __user *optval, int __user *optlen) +{ + struct sctp_association *asoc; + struct list_head *pos; + int cnt = 0; + struct sctp_getaddrs getaddrs; + struct sctp_transport *from; + void __user *to; + union sctp_addr temp; + struct sctp_sock *sp = sctp_sk(sk); + int addrlen; + size_t space_left; + int bytes_copied; + + if (len < sizeof(struct sctp_getaddrs)) + return -EINVAL; + + if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) + return -EFAULT; + + /* For UDP-style sockets, id specifies the association to query. */ + asoc = sctp_id2assoc(sk, getaddrs.assoc_id); + if (!asoc) + return -EINVAL; + + to = optval + offsetof(struct sctp_getaddrs,addrs); + space_left = len - sizeof(struct sctp_getaddrs) - + offsetof(struct sctp_getaddrs,addrs); + + list_for_each(pos, &asoc->peer.transport_addr_list) { + from = list_entry(pos, struct sctp_transport, transports); + memcpy(&temp, &from->ipaddr, sizeof(temp)); + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); + addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; + if(space_left < addrlen) + return -ENOMEM; + temp.v4.sin_port = htons(temp.v4.sin_port); + if (copy_to_user(to, &temp, addrlen)) + return -EFAULT; + to += addrlen; + cnt++; + space_left -= addrlen; + } + + if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) + return -EFAULT; + bytes_copied = ((char __user *)to) - optval; + if (put_user(bytes_copied, optlen)) return -EFAULT; return 0; } -static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len, - char __user *optval, - int __user *optlen) +static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, + char __user *optval, + int __user *optlen) { sctp_assoc_t id; struct sctp_bind_addr *bp; @@ -3306,8 +3366,8 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len, /* Helper function that copies local addresses to user and returns the number * of addresses copied. */ -static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, int max_addrs, - void __user *to) +static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_addrs, + void __user *to) { struct list_head *pos; struct sctp_sockaddr_entry *addr; @@ -3341,14 +3401,54 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, int max_addrs, return cnt; } -static int sctp_getsockopt_local_addrs(struct sock *sk, int len, - char __user *optval, int __user *optlen) +static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, + void * __user *to, size_t space_left) +{ + struct list_head *pos; + struct sctp_sockaddr_entry *addr; + unsigned long flags; + union sctp_addr temp; + int cnt = 0; + int addrlen; + + sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); + list_for_each(pos, &sctp_local_addr_list) { + addr = list_entry(pos, struct sctp_sockaddr_entry, list); + if ((PF_INET == sk->sk_family) && + (AF_INET6 == addr->a.sa.sa_family)) + continue; + memcpy(&temp, &addr->a, sizeof(temp)); + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), + &temp); + addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; + if(space_leftaddress_list.next, struct sctp_sockaddr_entry, list); if (sctp_is_any(&addr->a)) { - cnt = sctp_copy_laddrs_to_user(sk, bp->port, - getaddrs.addr_num, to); + cnt = sctp_copy_laddrs_to_user_old(sk, bp->port, + getaddrs.addr_num, + to); if (cnt < 0) { err = cnt; goto unlock; @@ -3419,7 +3520,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, copy_getaddrs: getaddrs.addr_num = cnt; - if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs))) + if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old))) err = -EFAULT; unlock: @@ -3427,6 +3528,99 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, return err; } +static int sctp_getsockopt_local_addrs(struct sock *sk, int len, + char __user *optval, int __user *optlen) +{ + struct sctp_bind_addr *bp; + struct sctp_association *asoc; + struct list_head *pos; + int cnt = 0; + struct sctp_getaddrs getaddrs; + struct sctp_sockaddr_entry *addr; + void __user *to; + union sctp_addr temp; + struct sctp_sock *sp = sctp_sk(sk); + int addrlen; + rwlock_t *addr_lock; + int err = 0; + size_t space_left; + int bytes_copied; + + if (len <= sizeof(struct sctp_getaddrs)) + return -EINVAL; + + if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) + return -EFAULT; + + /* + * For UDP-style sockets, id specifies the association to query. + * If the id field is set to the value '0' then the locally bound + * addresses are returned without regard to any particular + * association. + */ + if (0 == getaddrs.assoc_id) { + bp = &sctp_sk(sk)->ep->base.bind_addr; + addr_lock = &sctp_sk(sk)->ep->base.addr_lock; + } else { + asoc = sctp_id2assoc(sk, getaddrs.assoc_id); + if (!asoc) + return -EINVAL; + bp = &asoc->base.bind_addr; + addr_lock = &asoc->base.addr_lock; + } + + to = optval + offsetof(struct sctp_getaddrs,addrs); + space_left = len - sizeof(struct sctp_getaddrs) - + offsetof(struct sctp_getaddrs,addrs); + + sctp_read_lock(addr_lock); + + /* If the endpoint is bound to 0.0.0.0 or ::0, get the valid + * addresses from the global local address list. + */ + if (sctp_list_single_entry(&bp->address_list)) { + addr = list_entry(bp->address_list.next, + struct sctp_sockaddr_entry, list); + if (sctp_is_any(&addr->a)) { + cnt = sctp_copy_laddrs_to_user(sk, bp->port, + &to, space_left); + if (cnt < 0) { + err = cnt; + goto unlock; + } + goto copy_getaddrs; + } + } + + list_for_each(pos, &bp->address_list) { + addr = list_entry(pos, struct sctp_sockaddr_entry, list); + memcpy(&temp, &addr->a, sizeof(temp)); + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); + addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; + if(space_left < addrlen) + return -ENOMEM; /*fixme: right error?*/ + temp.v4.sin_port = htons(temp.v4.sin_port); + if (copy_to_user(to, &temp, addrlen)) { + err = -EFAULT; + goto unlock; + } + to += addrlen; + cnt ++; + space_left -= addrlen; + } + +copy_getaddrs: + if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) + return -EFAULT; + bytes_copied = ((char __user *)to) - optval; + if (put_user(bytes_copied, optlen)) + return -EFAULT; + +unlock: + sctp_read_unlock(addr_lock); + return err; +} + /* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) * * Requests that the local SCTP stack use the enclosed peer address as @@ -3807,12 +4001,20 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, case SCTP_INITMSG: retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); break; - case SCTP_GET_PEER_ADDRS_NUM: - retval = sctp_getsockopt_peer_addrs_num(sk, len, optval, + case SCTP_GET_PEER_ADDRS_NUM_OLD: + retval = sctp_getsockopt_peer_addrs_num_old(sk, len, optval, + optlen); + break; + case SCTP_GET_LOCAL_ADDRS_NUM_OLD: + retval = sctp_getsockopt_local_addrs_num_old(sk, len, optval, + optlen); + break; + case SCTP_GET_PEER_ADDRS_OLD: + retval = sctp_getsockopt_peer_addrs_old(sk, len, optval, optlen); break; - case SCTP_GET_LOCAL_ADDRS_NUM: - retval = sctp_getsockopt_local_addrs_num(sk, len, optval, + case SCTP_GET_LOCAL_ADDRS_OLD: + retval = sctp_getsockopt_local_addrs_old(sk, len, optval, optlen); break; case SCTP_GET_PEER_ADDRS: 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() */