diff options
-rw-r--r-- | Documentation/keys-request-key.txt | 161 | ||||
-rw-r--r-- | Documentation/keys.txt | 18 | ||||
-rw-r--r-- | arch/sparc/Kconfig | 4 | ||||
-rw-r--r-- | arch/sparc/defconfig | 1 | ||||
-rw-r--r-- | arch/sparc64/kernel/entry.S | 39 | ||||
-rw-r--r-- | arch/sparc64/kernel/power.c | 64 | ||||
-rw-r--r-- | arch/sparc64/kernel/rtrap.S | 7 | ||||
-rw-r--r-- | arch/sparc64/lib/VISsave.S | 8 | ||||
-rw-r--r-- | drivers/char/watchdog/pcwd_pci.c | 239 | ||||
-rw-r--r-- | drivers/pcmcia/ti113x.h | 5 | ||||
-rw-r--r-- | drivers/video/p9100.c | 4 | ||||
-rw-r--r-- | include/linux/atmdev.h | 10 | ||||
-rw-r--r-- | include/linux/key-ui.h | 91 | ||||
-rw-r--r-- | include/net/sctp/user.h | 33 | ||||
-rw-r--r-- | kernel/signal.c | 3 | ||||
-rw-r--r-- | net/atm/addr.c | 51 | ||||
-rw-r--r-- | net/atm/addr.h | 12 | ||||
-rw-r--r-- | net/atm/br2684.c | 2 | ||||
-rw-r--r-- | net/atm/resources.c | 20 | ||||
-rw-r--r-- | net/sctp/socket.c | 252 | ||||
-rw-r--r-- | security/keys/Makefile | 1 | ||||
-rw-r--r-- | security/keys/permission.c | 70 | ||||
-rw-r--r-- | security/keys/request_key.c | 2 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 3 |
24 files changed, 840 insertions, 260 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 @@ | |||
1 | =================== | ||
2 | KEY REQUEST SERVICE | ||
3 | =================== | ||
4 | |||
5 | The key request service is part of the key retention service (refer to | ||
6 | Documentation/keys.txt). This document explains more fully how that the | ||
7 | requesting algorithm works. | ||
8 | |||
9 | The process starts by either the kernel requesting a service by calling | ||
10 | request_key(): | ||
11 | |||
12 | struct key *request_key(const struct key_type *type, | ||
13 | const char *description, | ||
14 | const char *callout_string); | ||
15 | |||
16 | Or by userspace invoking the request_key system call: | ||
17 | |||
18 | key_serial_t request_key(const char *type, | ||
19 | const char *description, | ||
20 | const char *callout_info, | ||
21 | key_serial_t dest_keyring); | ||
22 | |||
23 | The main difference between the two access points is that the in-kernel | ||
24 | interface does not need to link the key to a keyring to prevent it from being | ||
25 | immediately destroyed. The kernel interface returns a pointer directly to the | ||
26 | key, and it's up to the caller to destroy the key. | ||
27 | |||
28 | The userspace interface links the key to a keyring associated with the process | ||
29 | to prevent the key from going away, and returns the serial number of the key to | ||
30 | the caller. | ||
31 | |||
32 | |||
33 | =========== | ||
34 | THE PROCESS | ||
35 | =========== | ||
36 | |||
37 | A request proceeds in the following manner: | ||
38 | |||
39 | (1) Process A calls request_key() [the userspace syscall calls the kernel | ||
40 | interface]. | ||
41 | |||
42 | (2) request_key() searches the process's subscribed keyrings to see if there's | ||
43 | a suitable key there. If there is, it returns the key. If there isn't, and | ||
44 | callout_info is not set, an error is returned. Otherwise the process | ||
45 | proceeds to the next step. | ||
46 | |||
47 | (3) request_key() sees that A doesn't have the desired key yet, so it creates | ||
48 | two things: | ||
49 | |||
50 | (a) An uninstantiated key U of requested type and description. | ||
51 | |||
52 | (b) An authorisation key V that refers to key U and notes that process A | ||
53 | is the context in which key U should be instantiated and secured, and | ||
54 | from which associated key requests may be satisfied. | ||
55 | |||
56 | (4) request_key() then forks and executes /sbin/request-key with a new session | ||
57 | keyring that contains a link to auth key V. | ||
58 | |||
59 | (5) /sbin/request-key execs an appropriate program to perform the actual | ||
60 | instantiation. | ||
61 | |||
62 | (6) The program may want to access another key from A's context (say a | ||
63 | Kerberos TGT key). It just requests the appropriate key, and the keyring | ||
64 | search notes that the session keyring has auth key V in its bottom level. | ||
65 | |||
66 | This will permit it to then search the keyrings of process A with the | ||
67 | UID, GID, groups and security info of process A as if it was process A, | ||
68 | and come up with key W. | ||
69 | |||
70 | (7) The program then does what it must to get the data with which to | ||
71 | instantiate key U, using key W as a reference (perhaps it contacts a | ||
72 | Kerberos server using the TGT) and then instantiates key U. | ||
73 | |||
74 | (8) Upon instantiating key U, auth key V is automatically revoked so that it | ||
75 | may not be used again. | ||
76 | |||
77 | (9) The program then exits 0 and request_key() deletes key V and returns key | ||
78 | U to the caller. | ||
79 | |||
80 | This also extends further. If key W (step 5 above) didn't exist, key W would be | ||
81 | created uninstantiated, another auth key (X) would be created [as per step 3] | ||
82 | and another copy of /sbin/request-key spawned [as per step 4]; but the context | ||
83 | specified by auth key X will still be process A, as it was in auth key V. | ||
84 | |||
85 | This is because process A's keyrings can't simply be attached to | ||
86 | /sbin/request-key at the appropriate places because (a) execve will discard two | ||
87 | of them, and (b) it requires the same UID/GID/Groups all the way through. | ||
88 | |||
89 | |||
90 | ====================== | ||
91 | NEGATIVE INSTANTIATION | ||
92 | ====================== | ||
93 | |||
94 | Rather than instantiating a key, it is possible for the possessor of an | ||
95 | authorisation key to negatively instantiate a key that's under construction. | ||
96 | This is a short duration placeholder that causes any attempt at re-requesting | ||
97 | the key whilst it exists to fail with error ENOKEY. | ||
98 | |||
99 | This is provided to prevent excessive repeated spawning of /sbin/request-key | ||
100 | processes for a key that will never be obtainable. | ||
101 | |||
102 | Should the /sbin/request-key process exit anything other than 0 or die on a | ||
103 | signal, the key under construction will be automatically negatively | ||
104 | instantiated for a short amount of time. | ||
105 | |||
106 | |||
107 | ==================== | ||
108 | THE SEARCH ALGORITHM | ||
109 | ==================== | ||
110 | |||
111 | A search of any particular keyring proceeds in the following fashion: | ||
112 | |||
113 | (1) When the key management code searches for a key (keyring_search_aux) it | ||
114 | firstly calls key_permission(SEARCH) on the keyring it's starting with, | ||
115 | if this denies permission, it doesn't search further. | ||
116 | |||
117 | (2) It considers all the non-keyring keys within that keyring and, if any key | ||
118 | matches the criteria specified, calls key_permission(SEARCH) on it to see | ||
119 | if the key is allowed to be found. If it is, that key is returned; if | ||
120 | not, the search continues, and the error code is retained if of higher | ||
121 | priority than the one currently set. | ||
122 | |||
123 | (3) It then considers all the keyring-type keys in the keyring it's currently | ||
124 | searching. It calls key_permission(SEARCH) on each keyring, and if this | ||
125 | grants permission, it recurses, executing steps (2) and (3) on that | ||
126 | keyring. | ||
127 | |||
128 | The process stops immediately a valid key is found with permission granted to | ||
129 | use it. Any error from a previous match attempt is discarded and the key is | ||
130 | returned. | ||
131 | |||
132 | When search_process_keyrings() is invoked, it performs the following searches | ||
133 | until one succeeds: | ||
134 | |||
135 | (1) If extant, the process's thread keyring is searched. | ||
136 | |||
137 | (2) If extant, the process's process keyring is searched. | ||
138 | |||
139 | (3) The process's session keyring is searched. | ||
140 | |||
141 | (4) If the process has a request_key() authorisation key in its session | ||
142 | keyring then: | ||
143 | |||
144 | (a) If extant, the calling process's thread keyring is searched. | ||
145 | |||
146 | (b) If extant, the calling process's process keyring is searched. | ||
147 | |||
148 | (c) The calling process's session keyring is searched. | ||
149 | |||
150 | The moment one succeeds, all pending errors are discarded and the found key is | ||
151 | returned. | ||
152 | |||
153 | Only if all these fail does the whole thing fail with the highest priority | ||
154 | error. Note that several errors may have come from LSM. | ||
155 | |||
156 | The error priority is: | ||
157 | |||
158 | EKEYREVOKED > EKEYEXPIRED > ENOKEY | ||
159 | |||
160 | EACCES/EPERM are only returned on a direct search of a specific keyring where | ||
161 | 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: | |||
361 | /sbin/request-key will be invoked in an attempt to obtain a key. The | 361 | /sbin/request-key will be invoked in an attempt to obtain a key. The |
362 | callout_info string will be passed as an argument to the program. | 362 | callout_info string will be passed as an argument to the program. |
363 | 363 | ||
364 | See also Documentation/keys-request-key.txt. | ||
365 | |||
364 | 366 | ||
365 | The keyctl syscall functions are: | 367 | The keyctl syscall functions are: |
366 | 368 | ||
@@ -533,8 +535,8 @@ The keyctl syscall functions are: | |||
533 | 535 | ||
534 | (*) Read the payload data from a key: | 536 | (*) Read the payload data from a key: |
535 | 537 | ||
536 | key_serial_t keyctl(KEYCTL_READ, key_serial_t keyring, char *buffer, | 538 | long keyctl(KEYCTL_READ, key_serial_t keyring, char *buffer, |
537 | size_t buflen); | 539 | size_t buflen); |
538 | 540 | ||
539 | This function attempts to read the payload data from the specified key | 541 | This function attempts to read the payload data from the specified key |
540 | into the buffer. The process must have read permission on the key to | 542 | into the buffer. The process must have read permission on the key to |
@@ -555,9 +557,9 @@ The keyctl syscall functions are: | |||
555 | 557 | ||
556 | (*) Instantiate a partially constructed key. | 558 | (*) Instantiate a partially constructed key. |
557 | 559 | ||
558 | key_serial_t keyctl(KEYCTL_INSTANTIATE, key_serial_t key, | 560 | long keyctl(KEYCTL_INSTANTIATE, key_serial_t key, |
559 | const void *payload, size_t plen, | 561 | const void *payload, size_t plen, |
560 | key_serial_t keyring); | 562 | key_serial_t keyring); |
561 | 563 | ||
562 | If the kernel calls back to userspace to complete the instantiation of a | 564 | If the kernel calls back to userspace to complete the instantiation of a |
563 | key, userspace should use this call to supply data for the key before the | 565 | key, userspace should use this call to supply data for the key before the |
@@ -576,8 +578,8 @@ The keyctl syscall functions are: | |||
576 | 578 | ||
577 | (*) Negatively instantiate a partially constructed key. | 579 | (*) Negatively instantiate a partially constructed key. |
578 | 580 | ||
579 | key_serial_t keyctl(KEYCTL_NEGATE, key_serial_t key, | 581 | long keyctl(KEYCTL_NEGATE, key_serial_t key, |
580 | unsigned timeout, key_serial_t keyring); | 582 | unsigned timeout, key_serial_t keyring); |
581 | 583 | ||
582 | If the kernel calls back to userspace to complete the instantiation of a | 584 | If the kernel calls back to userspace to complete the instantiation of a |
583 | key, userspace should use this call mark the key as negative before the | 585 | key, userspace should use this call mark the key as negative before the |
@@ -688,6 +690,8 @@ payload contents" for more information. | |||
688 | If successful, the key will have been attached to the default keyring for | 690 | If successful, the key will have been attached to the default keyring for |
689 | implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING. | 691 | implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING. |
690 | 692 | ||
693 | See also Documentation/keys-request-key.txt. | ||
694 | |||
691 | 695 | ||
692 | (*) When it is no longer required, the key should be released using: | 696 | (*) When it is no longer required, the key should be released using: |
693 | 697 | ||
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 | |||
21 | bool | 21 | bool |
22 | default y | 22 | default y |
23 | 23 | ||
24 | config GENERIC_IOMAP | ||
25 | bool | ||
26 | default y | ||
27 | |||
24 | source "init/Kconfig" | 28 | source "init/Kconfig" |
25 | 29 | ||
26 | menu "General machine setup" | 30 | 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 | |||
5 | CONFIG_UID16=y | 5 | CONFIG_UID16=y |
6 | CONFIG_HIGHMEM=y | 6 | CONFIG_HIGHMEM=y |
7 | CONFIG_GENERIC_ISA_DMA=y | 7 | CONFIG_GENERIC_ISA_DMA=y |
8 | CONFIG_GENERIC_IOMAP=y | ||
8 | 9 | ||
9 | # | 10 | # |
10 | # Code maturity level options | 11 | # 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 @@ | |||
33 | /* This is trivial with the new code... */ | 33 | /* This is trivial with the new code... */ |
34 | .globl do_fpdis | 34 | .globl do_fpdis |
35 | do_fpdis: | 35 | do_fpdis: |
36 | sethi %hi(TSTATE_PEF), %g4 ! IEU0 | 36 | sethi %hi(TSTATE_PEF), %g4 |
37 | rdpr %tstate, %g5 | 37 | rdpr %tstate, %g5 |
38 | andcc %g5, %g4, %g0 | 38 | andcc %g5, %g4, %g0 |
39 | be,pt %xcc, 1f | 39 | be,pt %xcc, 1f |
@@ -50,18 +50,18 @@ do_fpdis: | |||
50 | add %g0, %g0, %g0 | 50 | add %g0, %g0, %g0 |
51 | ba,a,pt %xcc, rtrap_clr_l6 | 51 | ba,a,pt %xcc, rtrap_clr_l6 |
52 | 52 | ||
53 | 1: ldub [%g6 + TI_FPSAVED], %g5 ! Load Group | 53 | 1: ldub [%g6 + TI_FPSAVED], %g5 |
54 | wr %g0, FPRS_FEF, %fprs ! LSU Group+4bubbles | 54 | wr %g0, FPRS_FEF, %fprs |
55 | andcc %g5, FPRS_FEF, %g0 ! IEU1 Group | 55 | andcc %g5, FPRS_FEF, %g0 |
56 | be,a,pt %icc, 1f ! CTI | 56 | be,a,pt %icc, 1f |
57 | clr %g7 ! IEU0 | 57 | clr %g7 |
58 | ldx [%g6 + TI_GSR], %g7 ! Load Group | 58 | ldx [%g6 + TI_GSR], %g7 |
59 | 1: andcc %g5, FPRS_DL, %g0 ! IEU1 | 59 | 1: andcc %g5, FPRS_DL, %g0 |
60 | bne,pn %icc, 2f ! CTI | 60 | bne,pn %icc, 2f |
61 | fzero %f0 ! FPA | 61 | fzero %f0 |
62 | andcc %g5, FPRS_DU, %g0 ! IEU1 Group | 62 | andcc %g5, FPRS_DU, %g0 |
63 | bne,pn %icc, 1f ! CTI | 63 | bne,pn %icc, 1f |
64 | fzero %f2 ! FPA | 64 | fzero %f2 |
65 | faddd %f0, %f2, %f4 | 65 | faddd %f0, %f2, %f4 |
66 | fmuld %f0, %f2, %f6 | 66 | fmuld %f0, %f2, %f6 |
67 | faddd %f0, %f2, %f8 | 67 | faddd %f0, %f2, %f8 |
@@ -104,8 +104,10 @@ do_fpdis: | |||
104 | add %g6, TI_FPREGS + 0xc0, %g2 | 104 | add %g6, TI_FPREGS + 0xc0, %g2 |
105 | faddd %f0, %f2, %f8 | 105 | faddd %f0, %f2, %f8 |
106 | fmuld %f0, %f2, %f10 | 106 | fmuld %f0, %f2, %f10 |
107 | ldda [%g1] ASI_BLK_S, %f32 ! grrr, where is ASI_BLK_NUCLEUS 8-( | 107 | membar #Sync |
108 | ldda [%g1] ASI_BLK_S, %f32 | ||
108 | ldda [%g2] ASI_BLK_S, %f48 | 109 | ldda [%g2] ASI_BLK_S, %f48 |
110 | membar #Sync | ||
109 | faddd %f0, %f2, %f12 | 111 | faddd %f0, %f2, %f12 |
110 | fmuld %f0, %f2, %f14 | 112 | fmuld %f0, %f2, %f14 |
111 | faddd %f0, %f2, %f16 | 113 | faddd %f0, %f2, %f16 |
@@ -116,7 +118,6 @@ do_fpdis: | |||
116 | fmuld %f0, %f2, %f26 | 118 | fmuld %f0, %f2, %f26 |
117 | faddd %f0, %f2, %f28 | 119 | faddd %f0, %f2, %f28 |
118 | fmuld %f0, %f2, %f30 | 120 | fmuld %f0, %f2, %f30 |
119 | membar #Sync | ||
120 | b,pt %xcc, fpdis_exit | 121 | b,pt %xcc, fpdis_exit |
121 | nop | 122 | nop |
122 | 2: andcc %g5, FPRS_DU, %g0 | 123 | 2: andcc %g5, FPRS_DU, %g0 |
@@ -133,8 +134,10 @@ do_fpdis: | |||
133 | add %g6, TI_FPREGS + 0x40, %g2 | 134 | add %g6, TI_FPREGS + 0x40, %g2 |
134 | faddd %f32, %f34, %f36 | 135 | faddd %f32, %f34, %f36 |
135 | fmuld %f32, %f34, %f38 | 136 | fmuld %f32, %f34, %f38 |
136 | ldda [%g1] ASI_BLK_S, %f0 ! grrr, where is ASI_BLK_NUCLEUS 8-( | 137 | membar #Sync |
138 | ldda [%g1] ASI_BLK_S, %f0 | ||
137 | ldda [%g2] ASI_BLK_S, %f16 | 139 | ldda [%g2] ASI_BLK_S, %f16 |
140 | membar #Sync | ||
138 | faddd %f32, %f34, %f40 | 141 | faddd %f32, %f34, %f40 |
139 | fmuld %f32, %f34, %f42 | 142 | fmuld %f32, %f34, %f42 |
140 | faddd %f32, %f34, %f44 | 143 | faddd %f32, %f34, %f44 |
@@ -147,7 +150,6 @@ do_fpdis: | |||
147 | fmuld %f32, %f34, %f58 | 150 | fmuld %f32, %f34, %f58 |
148 | faddd %f32, %f34, %f60 | 151 | faddd %f32, %f34, %f60 |
149 | fmuld %f32, %f34, %f62 | 152 | fmuld %f32, %f34, %f62 |
150 | membar #Sync | ||
151 | ba,pt %xcc, fpdis_exit | 153 | ba,pt %xcc, fpdis_exit |
152 | nop | 154 | nop |
153 | 3: mov SECONDARY_CONTEXT, %g3 | 155 | 3: mov SECONDARY_CONTEXT, %g3 |
@@ -158,7 +160,8 @@ do_fpdis: | |||
158 | stxa %g2, [%g3] ASI_DMMU | 160 | stxa %g2, [%g3] ASI_DMMU |
159 | membar #Sync | 161 | membar #Sync |
160 | mov 0x40, %g2 | 162 | mov 0x40, %g2 |
161 | ldda [%g1] ASI_BLK_S, %f0 ! grrr, where is ASI_BLK_NUCLEUS 8-( | 163 | membar #Sync |
164 | ldda [%g1] ASI_BLK_S, %f0 | ||
162 | ldda [%g1 + %g2] ASI_BLK_S, %f16 | 165 | ldda [%g1 + %g2] ASI_BLK_S, %f16 |
163 | add %g1, 0x80, %g1 | 166 | add %g1, 0x80, %g1 |
164 | ldda [%g1] ASI_BLK_S, %f32 | 167 | 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 @@ | |||
17 | 17 | ||
18 | #include <asm/system.h> | 18 | #include <asm/system.h> |
19 | #include <asm/ebus.h> | 19 | #include <asm/ebus.h> |
20 | #include <asm/isa.h> | ||
20 | #include <asm/auxio.h> | 21 | #include <asm/auxio.h> |
21 | 22 | ||
22 | #include <linux/unistd.h> | 23 | #include <linux/unistd.h> |
@@ -100,46 +101,83 @@ again: | |||
100 | return 0; | 101 | return 0; |
101 | } | 102 | } |
102 | 103 | ||
103 | static int __init has_button_interrupt(struct linux_ebus_device *edev) | 104 | static int __init has_button_interrupt(unsigned int irq, int prom_node) |
104 | { | 105 | { |
105 | if (edev->irqs[0] == PCI_IRQ_NONE) | 106 | if (irq == PCI_IRQ_NONE) |
106 | return 0; | 107 | return 0; |
107 | if (!prom_node_has_property(edev->prom_node, "button")) | 108 | if (!prom_node_has_property(prom_node, "button")) |
108 | return 0; | 109 | return 0; |
109 | 110 | ||
110 | return 1; | 111 | return 1; |
111 | } | 112 | } |
112 | 113 | ||
113 | void __init power_init(void) | 114 | static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p) |
114 | { | 115 | { |
115 | struct linux_ebus *ebus; | 116 | struct linux_ebus *ebus; |
116 | struct linux_ebus_device *edev; | 117 | struct linux_ebus_device *edev; |
118 | |||
119 | for_each_ebus(ebus) { | ||
120 | for_each_ebusdev(edev, ebus) { | ||
121 | if (!strcmp(edev->prom_name, "power")) { | ||
122 | *resp = &edev->resource[0]; | ||
123 | *irq_p = edev->irqs[0]; | ||
124 | *prom_node_p = edev->prom_node; | ||
125 | return 0; | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | return -ENODEV; | ||
130 | } | ||
131 | |||
132 | static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p) | ||
133 | { | ||
134 | struct sparc_isa_bridge *isa_bus; | ||
135 | struct sparc_isa_device *isa_dev; | ||
136 | |||
137 | for_each_isa(isa_bus) { | ||
138 | for_each_isadev(isa_dev, isa_bus) { | ||
139 | if (!strcmp(isa_dev->prom_name, "power")) { | ||
140 | *resp = &isa_dev->resource; | ||
141 | *irq_p = isa_dev->irq; | ||
142 | *prom_node_p = isa_dev->prom_node; | ||
143 | return 0; | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | return -ENODEV; | ||
148 | } | ||
149 | |||
150 | void __init power_init(void) | ||
151 | { | ||
152 | struct resource *res = NULL; | ||
153 | unsigned int irq; | ||
154 | int prom_node; | ||
117 | static int invoked; | 155 | static int invoked; |
118 | 156 | ||
119 | if (invoked) | 157 | if (invoked) |
120 | return; | 158 | return; |
121 | invoked = 1; | 159 | invoked = 1; |
122 | 160 | ||
123 | for_each_ebus(ebus) { | 161 | if (!power_probe_ebus(&res, &irq, &prom_node)) |
124 | for_each_ebusdev(edev, ebus) { | 162 | goto found; |
125 | if (!strcmp(edev->prom_name, "power")) | 163 | |
126 | goto found; | 164 | if (!power_probe_isa(&res, &irq, &prom_node)) |
127 | } | 165 | goto found; |
128 | } | 166 | |
129 | return; | 167 | return; |
130 | 168 | ||
131 | found: | 169 | found: |
132 | power_reg = ioremap(edev->resource[0].start, 0x4); | 170 | power_reg = ioremap(res->start, 0x4); |
133 | printk("power: Control reg at %p ... ", power_reg); | 171 | printk("power: Control reg at %p ... ", power_reg); |
134 | poweroff_method = machine_halt; /* able to use the standard halt */ | 172 | poweroff_method = machine_halt; /* able to use the standard halt */ |
135 | if (has_button_interrupt(edev)) { | 173 | if (has_button_interrupt(irq, prom_node)) { |
136 | if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { | 174 | if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { |
137 | printk("Failed to start power daemon.\n"); | 175 | printk("Failed to start power daemon.\n"); |
138 | return; | 176 | return; |
139 | } | 177 | } |
140 | printk("powerd running.\n"); | 178 | printk("powerd running.\n"); |
141 | 179 | ||
142 | if (request_irq(edev->irqs[0], | 180 | if (request_irq(irq, |
143 | power_handler, SA_SHIRQ, "power", NULL) < 0) | 181 | power_handler, SA_SHIRQ, "power", NULL) < 0) |
144 | printk("power: Error, cannot register IRQ handler.\n"); | 182 | printk("power: Error, cannot register IRQ handler.\n"); |
145 | } else { | 183 | } 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 | |||
312 | wr %g1, FPRS_FEF, %fprs | 312 | wr %g1, FPRS_FEF, %fprs |
313 | ldx [%o1 + %o5], %g1 | 313 | ldx [%o1 + %o5], %g1 |
314 | add %g6, TI_XFSR, %o1 | 314 | add %g6, TI_XFSR, %o1 |
315 | membar #StoreLoad | #LoadLoad | ||
316 | sll %o0, 8, %o2 | 315 | sll %o0, 8, %o2 |
317 | add %g6, TI_FPREGS, %o3 | 316 | add %g6, TI_FPREGS, %o3 |
318 | brz,pn %l6, 1f | 317 | brz,pn %l6, 1f |
319 | add %g6, TI_FPREGS+0x40, %o4 | 318 | add %g6, TI_FPREGS+0x40, %o4 |
320 | 319 | ||
320 | membar #Sync | ||
321 | ldda [%o3 + %o2] ASI_BLK_P, %f0 | 321 | ldda [%o3 + %o2] ASI_BLK_P, %f0 |
322 | ldda [%o4 + %o2] ASI_BLK_P, %f16 | 322 | ldda [%o4 + %o2] ASI_BLK_P, %f16 |
323 | membar #Sync | ||
323 | 1: andcc %l2, FPRS_DU, %g0 | 324 | 1: andcc %l2, FPRS_DU, %g0 |
324 | be,pn %icc, 1f | 325 | be,pn %icc, 1f |
325 | wr %g1, 0, %gsr | 326 | wr %g1, 0, %gsr |
326 | add %o2, 0x80, %o2 | 327 | add %o2, 0x80, %o2 |
328 | membar #Sync | ||
327 | ldda [%o3 + %o2] ASI_BLK_P, %f32 | 329 | ldda [%o3 + %o2] ASI_BLK_P, %f32 |
328 | ldda [%o4 + %o2] ASI_BLK_P, %f48 | 330 | ldda [%o4 + %o2] ASI_BLK_P, %f48 |
329 | |||
330 | 1: membar #Sync | 331 | 1: membar #Sync |
331 | ldx [%o1 + %o5], %fsr | 332 | ldx [%o1 + %o5], %fsr |
332 | 2: stb %l5, [%g6 + TI_FPDEPTH] | 333 | 2: stb %l5, [%g6 + TI_FPDEPTH] |
333 | ba,pt %xcc, rt_continue | 334 | ba,pt %xcc, rt_continue |
334 | nop | 335 | nop |
335 | 5: wr %g0, FPRS_FEF, %fprs | 336 | 5: wr %g0, FPRS_FEF, %fprs |
336 | membar #StoreLoad | #LoadLoad | ||
337 | sll %o0, 8, %o2 | 337 | sll %o0, 8, %o2 |
338 | 338 | ||
339 | add %g6, TI_FPREGS+0x80, %o3 | 339 | add %g6, TI_FPREGS+0x80, %o3 |
340 | add %g6, TI_FPREGS+0xc0, %o4 | 340 | add %g6, TI_FPREGS+0xc0, %o4 |
341 | membar #Sync | ||
341 | ldda [%o3 + %o2] ASI_BLK_P, %f32 | 342 | ldda [%o3 + %o2] ASI_BLK_P, %f32 |
342 | ldda [%o4 + %o2] ASI_BLK_P, %f48 | 343 | ldda [%o4 + %o2] ASI_BLK_P, %f48 |
343 | membar #Sync | 344 | 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 | |||
59 | be,pn %icc, 9b | 59 | be,pn %icc, 9b |
60 | add %g6, TI_FPREGS, %g2 | 60 | add %g6, TI_FPREGS, %g2 |
61 | andcc %o5, FPRS_DL, %g0 | 61 | andcc %o5, FPRS_DL, %g0 |
62 | membar #StoreStore | #LoadStore | ||
63 | 62 | ||
64 | be,pn %icc, 4f | 63 | be,pn %icc, 4f |
65 | add %g6, TI_FPREGS+0x40, %g3 | 64 | add %g6, TI_FPREGS+0x40, %g3 |
65 | membar #Sync | ||
66 | stda %f0, [%g2 + %g1] ASI_BLK_P | 66 | stda %f0, [%g2 + %g1] ASI_BLK_P |
67 | stda %f16, [%g3 + %g1] ASI_BLK_P | 67 | stda %f16, [%g3 + %g1] ASI_BLK_P |
68 | membar #Sync | ||
68 | andcc %o5, FPRS_DU, %g0 | 69 | andcc %o5, FPRS_DU, %g0 |
69 | be,pn %icc, 5f | 70 | be,pn %icc, 5f |
70 | 4: add %g1, 128, %g1 | 71 | 4: add %g1, 128, %g1 |
72 | membar #Sync | ||
71 | stda %f32, [%g2 + %g1] ASI_BLK_P | 73 | stda %f32, [%g2 + %g1] ASI_BLK_P |
72 | 74 | ||
73 | stda %f48, [%g3 + %g1] ASI_BLK_P | 75 | stda %f48, [%g3 + %g1] ASI_BLK_P |
@@ -87,7 +89,7 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 | |||
87 | sll %g1, 5, %g1 | 89 | sll %g1, 5, %g1 |
88 | add %g6, TI_FPREGS+0xc0, %g3 | 90 | add %g6, TI_FPREGS+0xc0, %g3 |
89 | wr %g0, FPRS_FEF, %fprs | 91 | wr %g0, FPRS_FEF, %fprs |
90 | membar #StoreStore | #LoadStore | 92 | membar #Sync |
91 | stda %f32, [%g2 + %g1] ASI_BLK_P | 93 | stda %f32, [%g2 + %g1] ASI_BLK_P |
92 | stda %f48, [%g3 + %g1] ASI_BLK_P | 94 | stda %f48, [%g3 + %g1] ASI_BLK_P |
93 | membar #Sync | 95 | membar #Sync |
@@ -128,8 +130,8 @@ VISenterhalf: | |||
128 | be,pn %icc, 4f | 130 | be,pn %icc, 4f |
129 | add %g6, TI_FPREGS, %g2 | 131 | add %g6, TI_FPREGS, %g2 |
130 | 132 | ||
131 | membar #StoreStore | #LoadStore | ||
132 | add %g6, TI_FPREGS+0x40, %g3 | 133 | add %g6, TI_FPREGS+0x40, %g3 |
134 | membar #Sync | ||
133 | stda %f0, [%g2 + %g1] ASI_BLK_P | 135 | stda %f0, [%g2 + %g1] ASI_BLK_P |
134 | stda %f16, [%g3 + %g1] ASI_BLK_P | 136 | stda %f16, [%g3 + %g1] ASI_BLK_P |
135 | membar #Sync | 137 | membar #Sync |
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c index 5a80adbf8032..0b8e493be045 100644 --- a/drivers/char/watchdog/pcwd_pci.c +++ b/drivers/char/watchdog/pcwd_pci.c | |||
@@ -50,8 +50,8 @@ | |||
50 | #include <asm/io.h> /* For inb/outb/... */ | 50 | #include <asm/io.h> /* For inb/outb/... */ |
51 | 51 | ||
52 | /* Module and version information */ | 52 | /* Module and version information */ |
53 | #define WATCHDOG_VERSION "1.01" | 53 | #define WATCHDOG_VERSION "1.02" |
54 | #define WATCHDOG_DATE "02 Sep 2005" | 54 | #define WATCHDOG_DATE "03 Sep 2005" |
55 | #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog" | 55 | #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog" |
56 | #define WATCHDOG_NAME "pcwd_pci" | 56 | #define WATCHDOG_NAME "pcwd_pci" |
57 | #define PFX WATCHDOG_NAME ": " | 57 | #define PFX WATCHDOG_NAME ": " |
@@ -70,19 +70,30 @@ | |||
70 | * These are the defines that describe the control status bits for the | 70 | * These are the defines that describe the control status bits for the |
71 | * PCI-PC Watchdog card. | 71 | * PCI-PC Watchdog card. |
72 | */ | 72 | */ |
73 | #define WD_PCI_WTRP 0x01 /* Watchdog Trip status */ | 73 | /* Port 1 : Control Status #1 */ |
74 | #define WD_PCI_HRBT 0x02 /* Watchdog Heartbeat */ | 74 | #define WD_PCI_WTRP 0x01 /* Watchdog Trip status */ |
75 | #define WD_PCI_TTRP 0x04 /* Temperature Trip status */ | 75 | #define WD_PCI_HRBT 0x02 /* Watchdog Heartbeat */ |
76 | #define WD_PCI_TTRP 0x04 /* Temperature Trip status */ | ||
77 | #define WD_PCI_RL2A 0x08 /* Relay 2 Active */ | ||
78 | #define WD_PCI_RL1A 0x10 /* Relay 1 Active */ | ||
79 | #define WD_PCI_R2DS 0x40 /* Relay 2 Disable Temperature-trip/reset */ | ||
80 | #define WD_PCI_RLY2 0x80 /* Activate Relay 2 on the board */ | ||
81 | /* Port 2 : Control Status #2 */ | ||
82 | #define WD_PCI_WDIS 0x10 /* Watchdog Disable */ | ||
83 | #define WD_PCI_ENTP 0x20 /* Enable Temperature Trip Reset */ | ||
84 | #define WD_PCI_WRSP 0x40 /* Watchdog wrote response */ | ||
85 | #define WD_PCI_PCMD 0x80 /* PC has sent command */ | ||
76 | 86 | ||
77 | /* according to documentation max. time to process a command for the pci | 87 | /* according to documentation max. time to process a command for the pci |
78 | * watchdog card is 100 ms, so we give it 150 ms to do it's job */ | 88 | * watchdog card is 100 ms, so we give it 150 ms to do it's job */ |
79 | #define PCI_COMMAND_TIMEOUT 150 | 89 | #define PCI_COMMAND_TIMEOUT 150 |
80 | 90 | ||
81 | /* Watchdog's internal commands */ | 91 | /* Watchdog's internal commands */ |
82 | #define CMD_GET_STATUS 0x04 | 92 | #define CMD_GET_STATUS 0x04 |
83 | #define CMD_GET_FIRMWARE_VERSION 0x08 | 93 | #define CMD_GET_FIRMWARE_VERSION 0x08 |
84 | #define CMD_READ_WATCHDOG_TIMEOUT 0x18 | 94 | #define CMD_READ_WATCHDOG_TIMEOUT 0x18 |
85 | #define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 | 95 | #define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 |
96 | #define CMD_GET_CLEAR_RESET_COUNT 0x84 | ||
86 | 97 | ||
87 | /* We can only use 1 card due to the /dev/watchdog restriction */ | 98 | /* We can only use 1 card due to the /dev/watchdog restriction */ |
88 | static int cards_found; | 99 | static int cards_found; |
@@ -91,15 +102,22 @@ static int cards_found; | |||
91 | static int temp_panic; | 102 | static int temp_panic; |
92 | static unsigned long is_active; | 103 | static unsigned long is_active; |
93 | static char expect_release; | 104 | static char expect_release; |
94 | static struct { | 105 | static struct { /* this is private data for each PCI-PC watchdog card */ |
95 | int supports_temp; /* Wether or not the card has a temperature device */ | 106 | int supports_temp; /* Wether or not the card has a temperature device */ |
96 | int boot_status; /* The card's boot status */ | 107 | int boot_status; /* The card's boot status */ |
97 | unsigned long io_addr; /* The cards I/O address */ | 108 | unsigned long io_addr; /* The cards I/O address */ |
98 | spinlock_t io_lock; | 109 | spinlock_t io_lock; /* the lock for io operations */ |
99 | struct pci_dev *pdev; | 110 | struct pci_dev *pdev; /* the PCI-device */ |
100 | } pcipcwd_private; | 111 | } pcipcwd_private; |
101 | 112 | ||
102 | /* module parameters */ | 113 | /* module parameters */ |
114 | #define QUIET 0 /* Default */ | ||
115 | #define VERBOSE 1 /* Verbose */ | ||
116 | #define DEBUG 2 /* print fancy stuff too */ | ||
117 | static int debug = QUIET; | ||
118 | module_param(debug, int, 0); | ||
119 | MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)"); | ||
120 | |||
103 | #define WATCHDOG_HEARTBEAT 2 /* 2 sec default heartbeat */ | 121 | #define WATCHDOG_HEARTBEAT 2 /* 2 sec default heartbeat */ |
104 | static int heartbeat = WATCHDOG_HEARTBEAT; | 122 | static int heartbeat = WATCHDOG_HEARTBEAT; |
105 | module_param(heartbeat, int, 0); | 123 | module_param(heartbeat, int, 0); |
@@ -117,6 +135,10 @@ static int send_command(int cmd, int *msb, int *lsb) | |||
117 | { | 135 | { |
118 | int got_response, count; | 136 | int got_response, count; |
119 | 137 | ||
138 | if (debug >= DEBUG) | ||
139 | printk(KERN_DEBUG PFX "sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x\n", | ||
140 | cmd, *msb, *lsb); | ||
141 | |||
120 | spin_lock(&pcipcwd_private.io_lock); | 142 | spin_lock(&pcipcwd_private.io_lock); |
121 | /* If a command requires data it should be written first. | 143 | /* If a command requires data it should be written first. |
122 | * Data for commands with 8 bits of data should be written to port 4. | 144 | * Data for commands with 8 bits of data should be written to port 4. |
@@ -131,10 +153,19 @@ static int send_command(int cmd, int *msb, int *lsb) | |||
131 | /* wait till the pci card processed the command, signaled by | 153 | /* wait till the pci card processed the command, signaled by |
132 | * the WRSP bit in port 2 and give it a max. timeout of | 154 | * the WRSP bit in port 2 and give it a max. timeout of |
133 | * PCI_COMMAND_TIMEOUT to process */ | 155 | * PCI_COMMAND_TIMEOUT to process */ |
134 | got_response = inb_p(pcipcwd_private.io_addr + 2) & 0x40; | 156 | got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP; |
135 | for (count = 0; (count < PCI_COMMAND_TIMEOUT) && (!got_response); count++) { | 157 | for (count = 0; (count < PCI_COMMAND_TIMEOUT) && (!got_response); count++) { |
136 | mdelay(1); | 158 | mdelay(1); |
137 | got_response = inb_p(pcipcwd_private.io_addr + 2) & 0x40; | 159 | got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP; |
160 | } | ||
161 | |||
162 | if (debug >= DEBUG) { | ||
163 | if (got_response) { | ||
164 | printk(KERN_DEBUG PFX "time to process command was: %d ms\n", | ||
165 | count); | ||
166 | } else { | ||
167 | printk(KERN_DEBUG PFX "card did not respond on command!\n"); | ||
168 | } | ||
138 | } | 169 | } |
139 | 170 | ||
140 | if (got_response) { | 171 | if (got_response) { |
@@ -144,12 +175,66 @@ static int send_command(int cmd, int *msb, int *lsb) | |||
144 | 175 | ||
145 | /* clear WRSP bit */ | 176 | /* clear WRSP bit */ |
146 | inb_p(pcipcwd_private.io_addr + 6); | 177 | inb_p(pcipcwd_private.io_addr + 6); |
178 | |||
179 | if (debug >= DEBUG) | ||
180 | printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: msb=0x%02x lsb=0x%02x\n", | ||
181 | cmd, *msb, *lsb); | ||
147 | } | 182 | } |
183 | |||
148 | spin_unlock(&pcipcwd_private.io_lock); | 184 | spin_unlock(&pcipcwd_private.io_lock); |
149 | 185 | ||
150 | return got_response; | 186 | return got_response; |
151 | } | 187 | } |
152 | 188 | ||
189 | static inline void pcipcwd_check_temperature_support(void) | ||
190 | { | ||
191 | if (inb_p(pcipcwd_private.io_addr) != 0xF0) | ||
192 | pcipcwd_private.supports_temp = 1; | ||
193 | } | ||
194 | |||
195 | static int pcipcwd_get_option_switches(void) | ||
196 | { | ||
197 | int option_switches; | ||
198 | |||
199 | option_switches = inb_p(pcipcwd_private.io_addr + 3); | ||
200 | return option_switches; | ||
201 | } | ||
202 | |||
203 | static void pcipcwd_show_card_info(void) | ||
204 | { | ||
205 | int got_fw_rev, fw_rev_major, fw_rev_minor; | ||
206 | char fw_ver_str[20]; /* The cards firmware version */ | ||
207 | int option_switches; | ||
208 | |||
209 | got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); | ||
210 | if (got_fw_rev) { | ||
211 | sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); | ||
212 | } else { | ||
213 | sprintf(fw_ver_str, "<card no answer>"); | ||
214 | } | ||
215 | |||
216 | /* Get switch settings */ | ||
217 | option_switches = pcipcwd_get_option_switches(); | ||
218 | |||
219 | printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n", | ||
220 | (int) pcipcwd_private.io_addr, fw_ver_str, | ||
221 | (pcipcwd_private.supports_temp ? "with" : "without")); | ||
222 | |||
223 | printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", | ||
224 | option_switches, | ||
225 | ((option_switches & 0x10) ? "ON" : "OFF"), | ||
226 | ((option_switches & 0x08) ? "ON" : "OFF")); | ||
227 | |||
228 | if (pcipcwd_private.boot_status & WDIOF_CARDRESET) | ||
229 | printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n"); | ||
230 | |||
231 | if (pcipcwd_private.boot_status & WDIOF_OVERHEAT) | ||
232 | printk(KERN_INFO PFX "Card sensed a CPU Overheat\n"); | ||
233 | |||
234 | if (pcipcwd_private.boot_status == 0) | ||
235 | printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); | ||
236 | } | ||
237 | |||
153 | static int pcipcwd_start(void) | 238 | static int pcipcwd_start(void) |
154 | { | 239 | { |
155 | int stat_reg; | 240 | int stat_reg; |
@@ -161,11 +246,14 @@ static int pcipcwd_start(void) | |||
161 | stat_reg = inb_p(pcipcwd_private.io_addr + 2); | 246 | stat_reg = inb_p(pcipcwd_private.io_addr + 2); |
162 | spin_unlock(&pcipcwd_private.io_lock); | 247 | spin_unlock(&pcipcwd_private.io_lock); |
163 | 248 | ||
164 | if (stat_reg & 0x10) { | 249 | if (stat_reg & WD_PCI_WDIS) { |
165 | printk(KERN_ERR PFX "Card timer not enabled\n"); | 250 | printk(KERN_ERR PFX "Card timer not enabled\n"); |
166 | return -1; | 251 | return -1; |
167 | } | 252 | } |
168 | 253 | ||
254 | if (debug >= VERBOSE) | ||
255 | printk(KERN_DEBUG PFX "Watchdog started\n"); | ||
256 | |||
169 | return 0; | 257 | return 0; |
170 | } | 258 | } |
171 | 259 | ||
@@ -183,18 +271,25 @@ static int pcipcwd_stop(void) | |||
183 | stat_reg = inb_p(pcipcwd_private.io_addr + 2); | 271 | stat_reg = inb_p(pcipcwd_private.io_addr + 2); |
184 | spin_unlock(&pcipcwd_private.io_lock); | 272 | spin_unlock(&pcipcwd_private.io_lock); |
185 | 273 | ||
186 | if (!(stat_reg & 0x10)) { | 274 | if (!(stat_reg & WD_PCI_WDIS)) { |
187 | printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n"); | 275 | printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n"); |
188 | return -1; | 276 | return -1; |
189 | } | 277 | } |
190 | 278 | ||
279 | if (debug >= VERBOSE) | ||
280 | printk(KERN_DEBUG PFX "Watchdog stopped\n"); | ||
281 | |||
191 | return 0; | 282 | return 0; |
192 | } | 283 | } |
193 | 284 | ||
194 | static int pcipcwd_keepalive(void) | 285 | static int pcipcwd_keepalive(void) |
195 | { | 286 | { |
196 | /* Re-trigger watchdog by writing to port 0 */ | 287 | /* Re-trigger watchdog by writing to port 0 */ |
197 | outb_p(0x42, pcipcwd_private.io_addr); | 288 | outb_p(0x42, pcipcwd_private.io_addr); /* send out any data */ |
289 | |||
290 | if (debug >= DEBUG) | ||
291 | printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n"); | ||
292 | |||
198 | return 0; | 293 | return 0; |
199 | } | 294 | } |
200 | 295 | ||
@@ -210,29 +305,64 @@ static int pcipcwd_set_heartbeat(int t) | |||
210 | send_command(CMD_WRITE_WATCHDOG_TIMEOUT, &t_msb, &t_lsb); | 305 | send_command(CMD_WRITE_WATCHDOG_TIMEOUT, &t_msb, &t_lsb); |
211 | 306 | ||
212 | heartbeat = t; | 307 | heartbeat = t; |
308 | if (debug >= VERBOSE) | ||
309 | printk(KERN_DEBUG PFX "New heartbeat: %d\n", | ||
310 | heartbeat); | ||
311 | |||
213 | return 0; | 312 | return 0; |
214 | } | 313 | } |
215 | 314 | ||
216 | static int pcipcwd_get_status(int *status) | 315 | static int pcipcwd_get_status(int *status) |
217 | { | 316 | { |
218 | int new_status; | 317 | int control_status; |
219 | 318 | ||
220 | *status=0; | 319 | *status=0; |
221 | new_status = inb_p(pcipcwd_private.io_addr + 1); | 320 | control_status = inb_p(pcipcwd_private.io_addr + 1); |
222 | if (new_status & WD_PCI_WTRP) | 321 | if (control_status & WD_PCI_WTRP) |
223 | *status |= WDIOF_CARDRESET; | 322 | *status |= WDIOF_CARDRESET; |
224 | if (new_status & WD_PCI_TTRP) { | 323 | if (control_status & WD_PCI_TTRP) { |
225 | *status |= WDIOF_OVERHEAT; | 324 | *status |= WDIOF_OVERHEAT; |
226 | if (temp_panic) | 325 | if (temp_panic) |
227 | panic(PFX "Temperature overheat trip!\n"); | 326 | panic(PFX "Temperature overheat trip!\n"); |
228 | } | 327 | } |
229 | 328 | ||
329 | if (debug >= DEBUG) | ||
330 | printk(KERN_DEBUG PFX "Control Status #1: 0x%02x\n", | ||
331 | control_status); | ||
332 | |||
230 | return 0; | 333 | return 0; |
231 | } | 334 | } |
232 | 335 | ||
233 | static int pcipcwd_clear_status(void) | 336 | static int pcipcwd_clear_status(void) |
234 | { | 337 | { |
235 | outb_p(0x01, pcipcwd_private.io_addr + 1); | 338 | int control_status; |
339 | int msb; | ||
340 | int reset_counter; | ||
341 | |||
342 | if (debug >= VERBOSE) | ||
343 | printk(KERN_INFO PFX "clearing watchdog trip status & LED\n"); | ||
344 | |||
345 | control_status = inb_p(pcipcwd_private.io_addr + 1); | ||
346 | |||
347 | if (debug >= DEBUG) { | ||
348 | printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status); | ||
349 | printk(KERN_DEBUG PFX "sending: 0x%02x\n", | ||
350 | (control_status & WD_PCI_R2DS) | WD_PCI_WTRP); | ||
351 | } | ||
352 | |||
353 | /* clear trip status & LED and keep mode of relay 2 */ | ||
354 | outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, pcipcwd_private.io_addr + 1); | ||
355 | |||
356 | /* clear reset counter */ | ||
357 | msb=0; | ||
358 | reset_counter=0xff; | ||
359 | send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter); | ||
360 | |||
361 | if (debug >= DEBUG) { | ||
362 | printk(KERN_DEBUG PFX "reset count was: 0x%02x\n", | ||
363 | reset_counter); | ||
364 | } | ||
365 | |||
236 | return 0; | 366 | return 0; |
237 | } | 367 | } |
238 | 368 | ||
@@ -242,11 +372,18 @@ static int pcipcwd_get_temperature(int *temperature) | |||
242 | if (!pcipcwd_private.supports_temp) | 372 | if (!pcipcwd_private.supports_temp) |
243 | return -ENODEV; | 373 | return -ENODEV; |
244 | 374 | ||
375 | *temperature = inb_p(pcipcwd_private.io_addr); | ||
376 | |||
245 | /* | 377 | /* |
246 | * Convert celsius to fahrenheit, since this was | 378 | * Convert celsius to fahrenheit, since this was |
247 | * the decided 'standard' for this return value. | 379 | * the decided 'standard' for this return value. |
248 | */ | 380 | */ |
249 | *temperature = ((inb_p(pcipcwd_private.io_addr)) * 9 / 5) + 32; | 381 | *temperature = (*temperature * 9 / 5) + 32; |
382 | |||
383 | if (debug >= DEBUG) { | ||
384 | printk(KERN_DEBUG PFX "temperature is: %d F\n", | ||
385 | *temperature); | ||
386 | } | ||
250 | 387 | ||
251 | return 0; | 388 | return 0; |
252 | } | 389 | } |
@@ -256,7 +393,7 @@ static int pcipcwd_get_temperature(int *temperature) | |||
256 | */ | 393 | */ |
257 | 394 | ||
258 | static ssize_t pcipcwd_write(struct file *file, const char __user *data, | 395 | static ssize_t pcipcwd_write(struct file *file, const char __user *data, |
259 | size_t len, loff_t *ppos) | 396 | size_t len, loff_t *ppos) |
260 | { | 397 | { |
261 | /* See if we got the magic character 'V' and reload the timer */ | 398 | /* See if we got the magic character 'V' and reload the timer */ |
262 | if (len) { | 399 | if (len) { |
@@ -381,8 +518,11 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file, | |||
381 | static int pcipcwd_open(struct inode *inode, struct file *file) | 518 | static int pcipcwd_open(struct inode *inode, struct file *file) |
382 | { | 519 | { |
383 | /* /dev/watchdog can only be opened once */ | 520 | /* /dev/watchdog can only be opened once */ |
384 | if (test_and_set_bit(0, &is_active)) | 521 | if (test_and_set_bit(0, &is_active)) { |
522 | if (debug >= VERBOSE) | ||
523 | printk(KERN_ERR PFX "Attempt to open already opened device.\n"); | ||
385 | return -EBUSY; | 524 | return -EBUSY; |
525 | } | ||
386 | 526 | ||
387 | /* Activate */ | 527 | /* Activate */ |
388 | pcipcwd_start(); | 528 | pcipcwd_start(); |
@@ -492,19 +632,10 @@ static struct notifier_block pcipcwd_notifier = { | |||
492 | * Init & exit routines | 632 | * Init & exit routines |
493 | */ | 633 | */ |
494 | 634 | ||
495 | static inline void check_temperature_support(void) | ||
496 | { | ||
497 | if (inb_p(pcipcwd_private.io_addr) != 0xF0) | ||
498 | pcipcwd_private.supports_temp = 1; | ||
499 | } | ||
500 | |||
501 | static int __devinit pcipcwd_card_init(struct pci_dev *pdev, | 635 | static int __devinit pcipcwd_card_init(struct pci_dev *pdev, |
502 | const struct pci_device_id *ent) | 636 | const struct pci_device_id *ent) |
503 | { | 637 | { |
504 | int ret = -EIO; | 638 | int ret = -EIO; |
505 | int got_fw_rev, fw_rev_major, fw_rev_minor; | ||
506 | char fw_ver_str[20]; | ||
507 | char option_switches; | ||
508 | 639 | ||
509 | cards_found++; | 640 | cards_found++; |
510 | if (cards_found == 1) | 641 | if (cards_found == 1) |
@@ -546,36 +677,10 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev, | |||
546 | pcipcwd_stop(); | 677 | pcipcwd_stop(); |
547 | 678 | ||
548 | /* Check whether or not the card supports the temperature device */ | 679 | /* Check whether or not the card supports the temperature device */ |
549 | check_temperature_support(); | 680 | pcipcwd_check_temperature_support(); |
550 | |||
551 | /* Get the Firmware Version */ | ||
552 | got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); | ||
553 | if (got_fw_rev) { | ||
554 | sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); | ||
555 | } else { | ||
556 | sprintf(fw_ver_str, "<card no answer>"); | ||
557 | } | ||
558 | 681 | ||
559 | /* Get switch settings */ | 682 | /* Show info about the card itself */ |
560 | option_switches = inb_p(pcipcwd_private.io_addr + 3); | 683 | pcipcwd_show_card_info(); |
561 | |||
562 | printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n", | ||
563 | (int) pcipcwd_private.io_addr, fw_ver_str, | ||
564 | (pcipcwd_private.supports_temp ? "with" : "without")); | ||
565 | |||
566 | printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", | ||
567 | option_switches, | ||
568 | ((option_switches & 0x10) ? "ON" : "OFF"), | ||
569 | ((option_switches & 0x08) ? "ON" : "OFF")); | ||
570 | |||
571 | if (pcipcwd_private.boot_status & WDIOF_CARDRESET) | ||
572 | printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n"); | ||
573 | |||
574 | if (pcipcwd_private.boot_status & WDIOF_OVERHEAT) | ||
575 | printk(KERN_INFO PFX "Card sensed a CPU Overheat\n"); | ||
576 | |||
577 | if (pcipcwd_private.boot_status == 0) | ||
578 | printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); | ||
579 | 684 | ||
580 | /* Check that the heartbeat value is within it's range ; if not reset to the default */ | 685 | /* Check that the heartbeat value is within it's range ; if not reset to the default */ |
581 | if (pcipcwd_set_heartbeat(heartbeat)) { | 686 | if (pcipcwd_set_heartbeat(heartbeat)) { |
@@ -656,7 +761,7 @@ static struct pci_driver pcipcwd_driver = { | |||
656 | 761 | ||
657 | static int __init pcipcwd_init_module(void) | 762 | static int __init pcipcwd_init_module(void) |
658 | { | 763 | { |
659 | spin_lock_init (&pcipcwd_private.io_lock); | 764 | spin_lock_init(&pcipcwd_private.io_lock); |
660 | 765 | ||
661 | return pci_register_driver(&pcipcwd_driver); | 766 | return pci_register_driver(&pcipcwd_driver); |
662 | } | 767 | } |
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) | |||
873 | * Some fixup code to make everybody happy (TM). | 873 | * Some fixup code to make everybody happy (TM). |
874 | */ | 874 | */ |
875 | 875 | ||
876 | #ifdef CONFIG_CARDBUS | ||
876 | /** | 877 | /** |
877 | * set/clear various test bits: | 878 | * set/clear various test bits: |
878 | * Defaults to clear the bit. | 879 | * Defaults to clear the bit. |
@@ -927,7 +928,6 @@ static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus) | |||
927 | config_writeb(socket, ENE_TEST_C9, test_c9); | 928 | config_writeb(socket, ENE_TEST_C9, test_c9); |
928 | } | 929 | } |
929 | 930 | ||
930 | |||
931 | static int ene_override(struct yenta_socket *socket) | 931 | static int ene_override(struct yenta_socket *socket) |
932 | { | 932 | { |
933 | /* install tune_bridge() function */ | 933 | /* install tune_bridge() function */ |
@@ -935,6 +935,9 @@ static int ene_override(struct yenta_socket *socket) | |||
935 | 935 | ||
936 | return ti1250_override(socket); | 936 | return ti1250_override(socket); |
937 | } | 937 | } |
938 | #else | ||
939 | # define ene_override ti1250_override | ||
940 | #endif | ||
938 | 941 | ||
939 | #endif /* _LINUX_TI113X_H */ | 942 | #endif /* _LINUX_TI113X_H */ |
940 | 943 | ||
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) | |||
288 | all->par.physbase = sdev->reg_addrs[2].phys_addr; | 288 | all->par.physbase = sdev->reg_addrs[2].phys_addr; |
289 | 289 | ||
290 | sbusfb_fill_var(&all->info.var, sdev->prom_node, 8); | 290 | sbusfb_fill_var(&all->info.var, sdev->prom_node, 8); |
291 | all->info.var.red.length = 8; | ||
292 | all->info.var.green.length = 8; | ||
293 | all->info.var.blue.length = 8; | ||
291 | 294 | ||
292 | linebytes = prom_getintdefault(sdev->prom_node, "linebytes", | 295 | linebytes = prom_getintdefault(sdev->prom_node, "linebytes", |
293 | all->info.var.xres); | 296 | all->info.var.xres); |
@@ -323,6 +326,7 @@ static void p9100_init_one(struct sbus_dev *sdev) | |||
323 | kfree(all); | 326 | kfree(all); |
324 | return; | 327 | return; |
325 | } | 328 | } |
329 | fb_set_cmap(&all->info.cmap, &all->info); | ||
326 | 330 | ||
327 | list_add(&all->list, &p9100_list); | 331 | list_add(&all->list, &p9100_list); |
328 | 332 | ||
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index f1fd849e5535..aca9b344bd35 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h | |||
@@ -76,6 +76,13 @@ struct atm_dev_stats { | |||
76 | /* set interface ESI */ | 76 | /* set interface ESI */ |
77 | #define ATM_SETESIF _IOW('a',ATMIOC_ITF+13,struct atmif_sioc) | 77 | #define ATM_SETESIF _IOW('a',ATMIOC_ITF+13,struct atmif_sioc) |
78 | /* force interface ESI */ | 78 | /* force interface ESI */ |
79 | #define ATM_ADDLECSADDR _IOW('a', ATMIOC_ITF+14, struct atmif_sioc) | ||
80 | /* register a LECS address */ | ||
81 | #define ATM_DELLECSADDR _IOW('a', ATMIOC_ITF+15, struct atmif_sioc) | ||
82 | /* unregister a LECS address */ | ||
83 | #define ATM_GETLECSADDR _IOW('a', ATMIOC_ITF+16, struct atmif_sioc) | ||
84 | /* retrieve LECS address(es) */ | ||
85 | |||
79 | #define ATM_GETSTAT _IOW('a',ATMIOC_SARCOM+0,struct atmif_sioc) | 86 | #define ATM_GETSTAT _IOW('a',ATMIOC_SARCOM+0,struct atmif_sioc) |
80 | /* get AAL layer statistics */ | 87 | /* get AAL layer statistics */ |
81 | #define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc) | 88 | #define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc) |
@@ -328,6 +335,8 @@ struct atm_dev_addr { | |||
328 | struct list_head entry; /* next address */ | 335 | struct list_head entry; /* next address */ |
329 | }; | 336 | }; |
330 | 337 | ||
338 | enum atm_addr_type_t { ATM_ADDR_LOCAL, ATM_ADDR_LECS }; | ||
339 | |||
331 | struct atm_dev { | 340 | struct atm_dev { |
332 | const struct atmdev_ops *ops; /* device operations; NULL if unused */ | 341 | const struct atmdev_ops *ops; /* device operations; NULL if unused */ |
333 | const struct atmphy_ops *phy; /* PHY operations, may be undefined */ | 342 | const struct atmphy_ops *phy; /* PHY operations, may be undefined */ |
@@ -338,6 +347,7 @@ struct atm_dev { | |||
338 | void *phy_data; /* private PHY date */ | 347 | void *phy_data; /* private PHY date */ |
339 | unsigned long flags; /* device flags (ATM_DF_*) */ | 348 | unsigned long flags; /* device flags (ATM_DF_*) */ |
340 | struct list_head local; /* local ATM addresses */ | 349 | struct list_head local; /* local ATM addresses */ |
350 | struct list_head lecs; /* LECS ATM addresses learned via ILMI */ | ||
341 | unsigned char esi[ESI_LEN]; /* ESI ("MAC" addr) */ | 351 | unsigned char esi[ESI_LEN]; /* ESI ("MAC" addr) */ |
342 | struct atm_cirange ci_range; /* VPI/VCI range */ | 352 | struct atm_cirange ci_range; /* VPI/VCI range */ |
343 | struct k_atm_dev_stats stats; /* statistics */ | 353 | struct k_atm_dev_stats stats; /* statistics */ |
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 { | |||
38 | struct key *keys[0]; | 38 | struct key *keys[0]; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | |||
42 | /* | 41 | /* |
43 | * check to see whether permission is granted to use a key in the desired way | 42 | * check to see whether permission is granted to use a key in the desired way |
44 | */ | 43 | */ |
45 | static inline int key_permission(const key_ref_t key_ref, key_perm_t perm) | 44 | extern int key_task_permission(const key_ref_t key_ref, |
46 | { | 45 | struct task_struct *context, |
47 | struct key *key = key_ref_to_ptr(key_ref); | 46 | key_perm_t perm); |
48 | key_perm_t kperm; | ||
49 | |||
50 | if (is_key_possessed(key_ref)) | ||
51 | kperm = key->perm >> 24; | ||
52 | else if (key->uid == current->fsuid) | ||
53 | kperm = key->perm >> 16; | ||
54 | else if (key->gid != -1 && | ||
55 | key->perm & KEY_GRP_ALL && | ||
56 | in_group_p(key->gid) | ||
57 | ) | ||
58 | kperm = key->perm >> 8; | ||
59 | else | ||
60 | kperm = key->perm; | ||
61 | |||
62 | kperm = kperm & perm & KEY_ALL; | ||
63 | |||
64 | return kperm == perm; | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * check to see whether permission is granted to use a key in at least one of | ||
69 | * the desired ways | ||
70 | */ | ||
71 | static inline int key_any_permission(const key_ref_t key_ref, key_perm_t perm) | ||
72 | { | ||
73 | struct key *key = key_ref_to_ptr(key_ref); | ||
74 | key_perm_t kperm; | ||
75 | |||
76 | if (is_key_possessed(key_ref)) | ||
77 | kperm = key->perm >> 24; | ||
78 | else if (key->uid == current->fsuid) | ||
79 | kperm = key->perm >> 16; | ||
80 | else if (key->gid != -1 && | ||
81 | key->perm & KEY_GRP_ALL && | ||
82 | in_group_p(key->gid) | ||
83 | ) | ||
84 | kperm = key->perm >> 8; | ||
85 | else | ||
86 | kperm = key->perm; | ||
87 | 47 | ||
88 | kperm = kperm & perm & KEY_ALL; | 48 | static inline int key_permission(const key_ref_t key_ref, key_perm_t perm) |
89 | |||
90 | return kperm != 0; | ||
91 | } | ||
92 | |||
93 | static inline int key_task_groups_search(struct task_struct *tsk, gid_t gid) | ||
94 | { | ||
95 | int ret; | ||
96 | |||
97 | task_lock(tsk); | ||
98 | ret = groups_search(tsk->group_info, gid); | ||
99 | task_unlock(tsk); | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | static inline int key_task_permission(const key_ref_t key_ref, | ||
104 | struct task_struct *context, | ||
105 | key_perm_t perm) | ||
106 | { | 49 | { |
107 | struct key *key = key_ref_to_ptr(key_ref); | 50 | return key_task_permission(key_ref, current, perm); |
108 | key_perm_t kperm; | ||
109 | |||
110 | if (is_key_possessed(key_ref)) { | ||
111 | kperm = key->perm >> 24; | ||
112 | } | ||
113 | else if (key->uid == context->fsuid) { | ||
114 | kperm = key->perm >> 16; | ||
115 | } | ||
116 | else if (key->gid != -1 && | ||
117 | key->perm & KEY_GRP_ALL && ( | ||
118 | key->gid == context->fsgid || | ||
119 | key_task_groups_search(context, key->gid) | ||
120 | ) | ||
121 | ) { | ||
122 | kperm = key->perm >> 8; | ||
123 | } | ||
124 | else { | ||
125 | kperm = key->perm; | ||
126 | } | ||
127 | |||
128 | kperm = kperm & perm & KEY_ALL; | ||
129 | |||
130 | return kperm == perm; | ||
131 | |||
132 | } | 51 | } |
133 | 52 | ||
134 | extern key_ref_t lookup_user_key(struct task_struct *context, | 53 | extern key_ref_t lookup_user_key(struct task_struct *context, |
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index f6328aeddcce..1c5f19f995ad 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h | |||
@@ -103,16 +103,20 @@ enum sctp_optname { | |||
103 | #define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM | 103 | #define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM |
104 | SCTP_SOCKOPT_PEELOFF, /* peel off association. */ | 104 | SCTP_SOCKOPT_PEELOFF, /* peel off association. */ |
105 | #define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF | 105 | #define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF |
106 | SCTP_GET_PEER_ADDRS_NUM, /* Get number of peer addresss. */ | 106 | SCTP_GET_PEER_ADDRS_NUM_OLD, /* Get number of peer addresss. */ |
107 | #define SCTP_GET_PEER_ADDRS_NUM SCTP_GET_PEER_ADDRS_NUM | 107 | #define SCTP_GET_PEER_ADDRS_NUM_OLD SCTP_GET_PEER_ADDRS_NUM_OLD |
108 | SCTP_GET_PEER_ADDRS_OLD, /* Get all peer addresss. */ | ||
109 | #define SCTP_GET_PEER_ADDRS_OLD SCTP_GET_PEER_ADDRS_OLD | ||
110 | SCTP_GET_LOCAL_ADDRS_NUM_OLD, /* Get number of local addresss. */ | ||
111 | #define SCTP_GET_LOCAL_ADDRS_NUM_OLD SCTP_GET_LOCAL_ADDRS_NUM_OLD | ||
112 | SCTP_GET_LOCAL_ADDRS_OLD, /* Get all local addresss. */ | ||
113 | #define SCTP_GET_LOCAL_ADDRS_OLD SCTP_GET_LOCAL_ADDRS_OLD | ||
114 | SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */ | ||
115 | #define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX | ||
108 | SCTP_GET_PEER_ADDRS, /* Get all peer addresss. */ | 116 | SCTP_GET_PEER_ADDRS, /* Get all peer addresss. */ |
109 | #define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS | 117 | #define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS |
110 | SCTP_GET_LOCAL_ADDRS_NUM, /* Get number of local addresss. */ | ||
111 | #define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM | ||
112 | SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ | 118 | SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ |
113 | #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS | 119 | #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS |
114 | SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */ | ||
115 | #define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX | ||
116 | }; | 120 | }; |
117 | 121 | ||
118 | /* | 122 | /* |
@@ -239,7 +243,7 @@ struct sctp_paddr_change { | |||
239 | int spc_state; | 243 | int spc_state; |
240 | int spc_error; | 244 | int spc_error; |
241 | sctp_assoc_t spc_assoc_id; | 245 | sctp_assoc_t spc_assoc_id; |
242 | }; | 246 | } __attribute__((packed, aligned(4))); |
243 | 247 | ||
244 | /* | 248 | /* |
245 | * spc_state: 32 bits (signed integer) | 249 | * spc_state: 32 bits (signed integer) |
@@ -464,7 +468,7 @@ struct sctp_assocparams { | |||
464 | struct sctp_setpeerprim { | 468 | struct sctp_setpeerprim { |
465 | sctp_assoc_t sspp_assoc_id; | 469 | sctp_assoc_t sspp_assoc_id; |
466 | struct sockaddr_storage sspp_addr; | 470 | struct sockaddr_storage sspp_addr; |
467 | }; | 471 | } __attribute__((packed, aligned(4))); |
468 | 472 | ||
469 | /* | 473 | /* |
470 | * 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) | 474 | * 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) |
@@ -477,7 +481,7 @@ struct sctp_setpeerprim { | |||
477 | struct sctp_prim { | 481 | struct sctp_prim { |
478 | sctp_assoc_t ssp_assoc_id; | 482 | sctp_assoc_t ssp_assoc_id; |
479 | struct sockaddr_storage ssp_addr; | 483 | struct sockaddr_storage ssp_addr; |
480 | }; | 484 | } __attribute__((packed, aligned(4))); |
481 | 485 | ||
482 | /* | 486 | /* |
483 | * 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER) | 487 | * 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER) |
@@ -504,7 +508,7 @@ struct sctp_paddrparams { | |||
504 | struct sockaddr_storage spp_address; | 508 | struct sockaddr_storage spp_address; |
505 | __u32 spp_hbinterval; | 509 | __u32 spp_hbinterval; |
506 | __u16 spp_pathmaxrxt; | 510 | __u16 spp_pathmaxrxt; |
507 | }; | 511 | } __attribute__((packed, aligned(4))); |
508 | 512 | ||
509 | /* | 513 | /* |
510 | * 7.2.2 Peer Address Information | 514 | * 7.2.2 Peer Address Information |
@@ -523,7 +527,7 @@ struct sctp_paddrinfo { | |||
523 | __u32 spinfo_srtt; | 527 | __u32 spinfo_srtt; |
524 | __u32 spinfo_rto; | 528 | __u32 spinfo_rto; |
525 | __u32 spinfo_mtu; | 529 | __u32 spinfo_mtu; |
526 | }; | 530 | } __attribute__((packed, aligned(4))); |
527 | 531 | ||
528 | /* Peer addresses's state. */ | 532 | /* Peer addresses's state. */ |
529 | enum sctp_spinfo_state { | 533 | enum sctp_spinfo_state { |
@@ -559,11 +563,16 @@ struct sctp_status { | |||
559 | * SCTP_GET_LOCAL_ADDRS socket options used internally to implement | 563 | * SCTP_GET_LOCAL_ADDRS socket options used internally to implement |
560 | * sctp_getpaddrs() and sctp_getladdrs() API. | 564 | * sctp_getpaddrs() and sctp_getladdrs() API. |
561 | */ | 565 | */ |
562 | struct sctp_getaddrs { | 566 | struct sctp_getaddrs_old { |
563 | sctp_assoc_t assoc_id; | 567 | sctp_assoc_t assoc_id; |
564 | int addr_num; | 568 | int addr_num; |
565 | struct sockaddr __user *addrs; | 569 | struct sockaddr __user *addrs; |
566 | }; | 570 | }; |
571 | struct sctp_getaddrs { | ||
572 | sctp_assoc_t assoc_id; /*input*/ | ||
573 | __u32 addr_num; /*output*/ | ||
574 | __u8 addrs[0]; /*output, variable size*/ | ||
575 | }; | ||
567 | 576 | ||
568 | /* These are bit fields for msghdr->msg_flags. See section 5.1. */ | 577 | /* These are bit fields for msghdr->msg_flags. See section 5.1. */ |
569 | /* On user space Linux, these live in <bits/socket.h> as an enum. */ | 578 | /* On user space Linux, these live in <bits/socket.h> as an enum. */ |
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) | |||
578 | * is to alert stop-signal processing code when another | 578 | * is to alert stop-signal processing code when another |
579 | * processor has come along and cleared the flag. | 579 | * processor has come along and cleared the flag. |
580 | */ | 580 | */ |
581 | tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; | 581 | if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) |
582 | tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; | ||
582 | } | 583 | } |
583 | if ( signr && | 584 | if ( signr && |
584 | ((info->si_code & __SI_MASK) == __SI_TIMER) && | 585 | ((info->si_code & __SI_MASK) == __SI_TIMER) && |
diff --git a/net/atm/addr.c b/net/atm/addr.c index a30d0bf48063..3060fd0ba4b9 100644 --- a/net/atm/addr.c +++ b/net/atm/addr.c | |||
@@ -44,31 +44,43 @@ static void notify_sigd(struct atm_dev *dev) | |||
44 | sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL); | 44 | sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL); |
45 | } | 45 | } |
46 | 46 | ||
47 | void atm_reset_addr(struct atm_dev *dev) | 47 | void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t atype) |
48 | { | 48 | { |
49 | unsigned long flags; | 49 | unsigned long flags; |
50 | struct atm_dev_addr *this, *p; | 50 | struct atm_dev_addr *this, *p; |
51 | struct list_head *head; | ||
51 | 52 | ||
52 | spin_lock_irqsave(&dev->lock, flags); | 53 | spin_lock_irqsave(&dev->lock, flags); |
53 | list_for_each_entry_safe(this, p, &dev->local, entry) { | 54 | if (atype == ATM_ADDR_LECS) |
55 | head = &dev->lecs; | ||
56 | else | ||
57 | head = &dev->local; | ||
58 | list_for_each_entry_safe(this, p, head, entry) { | ||
54 | list_del(&this->entry); | 59 | list_del(&this->entry); |
55 | kfree(this); | 60 | kfree(this); |
56 | } | 61 | } |
57 | spin_unlock_irqrestore(&dev->lock, flags); | 62 | spin_unlock_irqrestore(&dev->lock, flags); |
58 | notify_sigd(dev); | 63 | if (head == &dev->local) |
64 | notify_sigd(dev); | ||
59 | } | 65 | } |
60 | 66 | ||
61 | int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) | 67 | int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, |
68 | enum atm_addr_type_t atype) | ||
62 | { | 69 | { |
63 | unsigned long flags; | 70 | unsigned long flags; |
64 | struct atm_dev_addr *this; | 71 | struct atm_dev_addr *this; |
72 | struct list_head *head; | ||
65 | int error; | 73 | int error; |
66 | 74 | ||
67 | error = check_addr(addr); | 75 | error = check_addr(addr); |
68 | if (error) | 76 | if (error) |
69 | return error; | 77 | return error; |
70 | spin_lock_irqsave(&dev->lock, flags); | 78 | spin_lock_irqsave(&dev->lock, flags); |
71 | list_for_each_entry(this, &dev->local, entry) { | 79 | if (atype == ATM_ADDR_LECS) |
80 | head = &dev->lecs; | ||
81 | else | ||
82 | head = &dev->local; | ||
83 | list_for_each_entry(this, head, entry) { | ||
72 | if (identical(&this->addr, addr)) { | 84 | if (identical(&this->addr, addr)) { |
73 | spin_unlock_irqrestore(&dev->lock, flags); | 85 | spin_unlock_irqrestore(&dev->lock, flags); |
74 | return -EEXIST; | 86 | return -EEXIST; |
@@ -80,28 +92,36 @@ int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) | |||
80 | return -ENOMEM; | 92 | return -ENOMEM; |
81 | } | 93 | } |
82 | this->addr = *addr; | 94 | this->addr = *addr; |
83 | list_add(&this->entry, &dev->local); | 95 | list_add(&this->entry, head); |
84 | spin_unlock_irqrestore(&dev->lock, flags); | 96 | spin_unlock_irqrestore(&dev->lock, flags); |
85 | notify_sigd(dev); | 97 | if (head == &dev->local) |
98 | notify_sigd(dev); | ||
86 | return 0; | 99 | return 0; |
87 | } | 100 | } |
88 | 101 | ||
89 | int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) | 102 | int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, |
103 | enum atm_addr_type_t atype) | ||
90 | { | 104 | { |
91 | unsigned long flags; | 105 | unsigned long flags; |
92 | struct atm_dev_addr *this; | 106 | struct atm_dev_addr *this; |
107 | struct list_head *head; | ||
93 | int error; | 108 | int error; |
94 | 109 | ||
95 | error = check_addr(addr); | 110 | error = check_addr(addr); |
96 | if (error) | 111 | if (error) |
97 | return error; | 112 | return error; |
98 | spin_lock_irqsave(&dev->lock, flags); | 113 | spin_lock_irqsave(&dev->lock, flags); |
99 | list_for_each_entry(this, &dev->local, entry) { | 114 | if (atype == ATM_ADDR_LECS) |
115 | head = &dev->lecs; | ||
116 | else | ||
117 | head = &dev->local; | ||
118 | list_for_each_entry(this, head, entry) { | ||
100 | if (identical(&this->addr, addr)) { | 119 | if (identical(&this->addr, addr)) { |
101 | list_del(&this->entry); | 120 | list_del(&this->entry); |
102 | spin_unlock_irqrestore(&dev->lock, flags); | 121 | spin_unlock_irqrestore(&dev->lock, flags); |
103 | kfree(this); | 122 | kfree(this); |
104 | notify_sigd(dev); | 123 | if (head == &dev->local) |
124 | notify_sigd(dev); | ||
105 | return 0; | 125 | return 0; |
106 | } | 126 | } |
107 | } | 127 | } |
@@ -110,22 +130,27 @@ int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) | |||
110 | } | 130 | } |
111 | 131 | ||
112 | int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf, | 132 | int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf, |
113 | size_t size) | 133 | size_t size, enum atm_addr_type_t atype) |
114 | { | 134 | { |
115 | unsigned long flags; | 135 | unsigned long flags; |
116 | struct atm_dev_addr *this; | 136 | struct atm_dev_addr *this; |
137 | struct list_head *head; | ||
117 | int total = 0, error; | 138 | int total = 0, error; |
118 | struct sockaddr_atmsvc *tmp_buf, *tmp_bufp; | 139 | struct sockaddr_atmsvc *tmp_buf, *tmp_bufp; |
119 | 140 | ||
120 | spin_lock_irqsave(&dev->lock, flags); | 141 | spin_lock_irqsave(&dev->lock, flags); |
121 | list_for_each_entry(this, &dev->local, entry) | 142 | if (atype == ATM_ADDR_LECS) |
143 | head = &dev->lecs; | ||
144 | else | ||
145 | head = &dev->local; | ||
146 | list_for_each_entry(this, head, entry) | ||
122 | total += sizeof(struct sockaddr_atmsvc); | 147 | total += sizeof(struct sockaddr_atmsvc); |
123 | tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC); | 148 | tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC); |
124 | if (!tmp_buf) { | 149 | if (!tmp_buf) { |
125 | spin_unlock_irqrestore(&dev->lock, flags); | 150 | spin_unlock_irqrestore(&dev->lock, flags); |
126 | return -ENOMEM; | 151 | return -ENOMEM; |
127 | } | 152 | } |
128 | list_for_each_entry(this, &dev->local, entry) | 153 | list_for_each_entry(this, head, entry) |
129 | memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc)); | 154 | memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc)); |
130 | spin_unlock_irqrestore(&dev->lock, flags); | 155 | spin_unlock_irqrestore(&dev->lock, flags); |
131 | error = total > size ? -E2BIG : total; | 156 | error = total > size ? -E2BIG : total; |
diff --git a/net/atm/addr.h b/net/atm/addr.h index 3099d21feeaa..f39433ad45da 100644 --- a/net/atm/addr.h +++ b/net/atm/addr.h | |||
@@ -9,10 +9,12 @@ | |||
9 | #include <linux/atm.h> | 9 | #include <linux/atm.h> |
10 | #include <linux/atmdev.h> | 10 | #include <linux/atmdev.h> |
11 | 11 | ||
12 | 12 | void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t type); | |
13 | void atm_reset_addr(struct atm_dev *dev); | 13 | int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, |
14 | int atm_add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); | 14 | enum atm_addr_type_t type); |
15 | int atm_del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); | 15 | int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, |
16 | int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc __user *buf,size_t size); | 16 | enum atm_addr_type_t type); |
17 | int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user *buf, | ||
18 | size_t size, enum atm_addr_type_t type); | ||
17 | 19 | ||
18 | #endif | 20 | #endif |
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 289956c4dd3e..72f3f7b8de80 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
@@ -220,7 +220,7 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
220 | /* netif_stop_queue(dev); */ | 220 | /* netif_stop_queue(dev); */ |
221 | dev_kfree_skb(skb); | 221 | dev_kfree_skb(skb); |
222 | read_unlock(&devs_lock); | 222 | read_unlock(&devs_lock); |
223 | return -EUNATCH; | 223 | return 0; |
224 | } | 224 | } |
225 | if (!br2684_xmit_vcc(skb, brdev, brvcc)) { | 225 | if (!br2684_xmit_vcc(skb, brdev, brvcc)) { |
226 | /* | 226 | /* |
diff --git a/net/atm/resources.c b/net/atm/resources.c index a57a9268bd24..415d2615d475 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c | |||
@@ -40,6 +40,7 @@ static struct atm_dev *__alloc_atm_dev(const char *type) | |||
40 | dev->link_rate = ATM_OC3_PCR; | 40 | dev->link_rate = ATM_OC3_PCR; |
41 | spin_lock_init(&dev->lock); | 41 | spin_lock_init(&dev->lock); |
42 | INIT_LIST_HEAD(&dev->local); | 42 | INIT_LIST_HEAD(&dev->local); |
43 | INIT_LIST_HEAD(&dev->lecs); | ||
43 | 44 | ||
44 | return dev; | 45 | return dev; |
45 | } | 46 | } |
@@ -320,10 +321,12 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) | |||
320 | error = -EPERM; | 321 | error = -EPERM; |
321 | goto done; | 322 | goto done; |
322 | } | 323 | } |
323 | atm_reset_addr(dev); | 324 | atm_reset_addr(dev, ATM_ADDR_LOCAL); |
324 | break; | 325 | break; |
325 | case ATM_ADDADDR: | 326 | case ATM_ADDADDR: |
326 | case ATM_DELADDR: | 327 | case ATM_DELADDR: |
328 | case ATM_ADDLECSADDR: | ||
329 | case ATM_DELLECSADDR: | ||
327 | if (!capable(CAP_NET_ADMIN)) { | 330 | if (!capable(CAP_NET_ADMIN)) { |
328 | error = -EPERM; | 331 | error = -EPERM; |
329 | goto done; | 332 | goto done; |
@@ -335,14 +338,21 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) | |||
335 | error = -EFAULT; | 338 | error = -EFAULT; |
336 | goto done; | 339 | goto done; |
337 | } | 340 | } |
338 | if (cmd == ATM_ADDADDR) | 341 | if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR) |
339 | error = atm_add_addr(dev, &addr); | 342 | error = atm_add_addr(dev, &addr, |
343 | (cmd == ATM_ADDADDR ? | ||
344 | ATM_ADDR_LOCAL : ATM_ADDR_LECS)); | ||
340 | else | 345 | else |
341 | error = atm_del_addr(dev, &addr); | 346 | error = atm_del_addr(dev, &addr, |
347 | (cmd == ATM_DELADDR ? | ||
348 | ATM_ADDR_LOCAL : ATM_ADDR_LECS)); | ||
342 | goto done; | 349 | goto done; |
343 | } | 350 | } |
344 | case ATM_GETADDR: | 351 | case ATM_GETADDR: |
345 | error = atm_get_addr(dev, buf, len); | 352 | case ATM_GETLECSADDR: |
353 | error = atm_get_addr(dev, buf, len, | ||
354 | (cmd == ATM_GETADDR ? | ||
355 | ATM_ADDR_LOCAL : ATM_ADDR_LECS)); | ||
346 | if (error < 0) | 356 | if (error < 0) |
347 | goto done; | 357 | goto done; |
348 | size = error; | 358 | size = error; |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 91ec8c936913..02e068d3450d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -3159,8 +3159,9 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval | |||
3159 | return 0; | 3159 | return 0; |
3160 | } | 3160 | } |
3161 | 3161 | ||
3162 | static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, | 3162 | static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len, |
3163 | char __user *optval, int __user *optlen) | 3163 | char __user *optval, |
3164 | int __user *optlen) | ||
3164 | { | 3165 | { |
3165 | sctp_assoc_t id; | 3166 | sctp_assoc_t id; |
3166 | struct sctp_association *asoc; | 3167 | struct sctp_association *asoc; |
@@ -3185,23 +3186,28 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, | |||
3185 | return cnt; | 3186 | return cnt; |
3186 | } | 3187 | } |
3187 | 3188 | ||
3188 | static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, | 3189 | /* |
3189 | char __user *optval, int __user *optlen) | 3190 | * Old API for getting list of peer addresses. Does not work for 32-bit |
3191 | * programs running on a 64-bit kernel | ||
3192 | */ | ||
3193 | static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len, | ||
3194 | char __user *optval, | ||
3195 | int __user *optlen) | ||
3190 | { | 3196 | { |
3191 | struct sctp_association *asoc; | 3197 | struct sctp_association *asoc; |
3192 | struct list_head *pos; | 3198 | struct list_head *pos; |
3193 | int cnt = 0; | 3199 | int cnt = 0; |
3194 | struct sctp_getaddrs getaddrs; | 3200 | struct sctp_getaddrs_old getaddrs; |
3195 | struct sctp_transport *from; | 3201 | struct sctp_transport *from; |
3196 | void __user *to; | 3202 | void __user *to; |
3197 | union sctp_addr temp; | 3203 | union sctp_addr temp; |
3198 | struct sctp_sock *sp = sctp_sk(sk); | 3204 | struct sctp_sock *sp = sctp_sk(sk); |
3199 | int addrlen; | 3205 | int addrlen; |
3200 | 3206 | ||
3201 | if (len != sizeof(struct sctp_getaddrs)) | 3207 | if (len != sizeof(struct sctp_getaddrs_old)) |
3202 | return -EINVAL; | 3208 | return -EINVAL; |
3203 | 3209 | ||
3204 | if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) | 3210 | if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old))) |
3205 | return -EFAULT; | 3211 | return -EFAULT; |
3206 | 3212 | ||
3207 | if (getaddrs.addr_num <= 0) return -EINVAL; | 3213 | if (getaddrs.addr_num <= 0) return -EINVAL; |
@@ -3225,15 +3231,69 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, | |||
3225 | if (cnt >= getaddrs.addr_num) break; | 3231 | if (cnt >= getaddrs.addr_num) break; |
3226 | } | 3232 | } |
3227 | getaddrs.addr_num = cnt; | 3233 | getaddrs.addr_num = cnt; |
3228 | if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs))) | 3234 | if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old))) |
3235 | return -EFAULT; | ||
3236 | |||
3237 | return 0; | ||
3238 | } | ||
3239 | |||
3240 | static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, | ||
3241 | char __user *optval, int __user *optlen) | ||
3242 | { | ||
3243 | struct sctp_association *asoc; | ||
3244 | struct list_head *pos; | ||
3245 | int cnt = 0; | ||
3246 | struct sctp_getaddrs getaddrs; | ||
3247 | struct sctp_transport *from; | ||
3248 | void __user *to; | ||
3249 | union sctp_addr temp; | ||
3250 | struct sctp_sock *sp = sctp_sk(sk); | ||
3251 | int addrlen; | ||
3252 | size_t space_left; | ||
3253 | int bytes_copied; | ||
3254 | |||
3255 | if (len < sizeof(struct sctp_getaddrs)) | ||
3256 | return -EINVAL; | ||
3257 | |||
3258 | if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) | ||
3259 | return -EFAULT; | ||
3260 | |||
3261 | /* For UDP-style sockets, id specifies the association to query. */ | ||
3262 | asoc = sctp_id2assoc(sk, getaddrs.assoc_id); | ||
3263 | if (!asoc) | ||
3264 | return -EINVAL; | ||
3265 | |||
3266 | to = optval + offsetof(struct sctp_getaddrs,addrs); | ||
3267 | space_left = len - sizeof(struct sctp_getaddrs) - | ||
3268 | offsetof(struct sctp_getaddrs,addrs); | ||
3269 | |||
3270 | list_for_each(pos, &asoc->peer.transport_addr_list) { | ||
3271 | from = list_entry(pos, struct sctp_transport, transports); | ||
3272 | memcpy(&temp, &from->ipaddr, sizeof(temp)); | ||
3273 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); | ||
3274 | addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; | ||
3275 | if(space_left < addrlen) | ||
3276 | return -ENOMEM; | ||
3277 | temp.v4.sin_port = htons(temp.v4.sin_port); | ||
3278 | if (copy_to_user(to, &temp, addrlen)) | ||
3279 | return -EFAULT; | ||
3280 | to += addrlen; | ||
3281 | cnt++; | ||
3282 | space_left -= addrlen; | ||
3283 | } | ||
3284 | |||
3285 | if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) | ||
3286 | return -EFAULT; | ||
3287 | bytes_copied = ((char __user *)to) - optval; | ||
3288 | if (put_user(bytes_copied, optlen)) | ||
3229 | return -EFAULT; | 3289 | return -EFAULT; |
3230 | 3290 | ||
3231 | return 0; | 3291 | return 0; |
3232 | } | 3292 | } |
3233 | 3293 | ||
3234 | static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len, | 3294 | static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, |
3235 | char __user *optval, | 3295 | char __user *optval, |
3236 | int __user *optlen) | 3296 | int __user *optlen) |
3237 | { | 3297 | { |
3238 | sctp_assoc_t id; | 3298 | sctp_assoc_t id; |
3239 | struct sctp_bind_addr *bp; | 3299 | struct sctp_bind_addr *bp; |
@@ -3306,8 +3366,8 @@ done: | |||
3306 | /* Helper function that copies local addresses to user and returns the number | 3366 | /* Helper function that copies local addresses to user and returns the number |
3307 | * of addresses copied. | 3367 | * of addresses copied. |
3308 | */ | 3368 | */ |
3309 | static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, int max_addrs, | 3369 | static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_addrs, |
3310 | void __user *to) | 3370 | void __user *to) |
3311 | { | 3371 | { |
3312 | struct list_head *pos; | 3372 | struct list_head *pos; |
3313 | struct sctp_sockaddr_entry *addr; | 3373 | struct sctp_sockaddr_entry *addr; |
@@ -3341,14 +3401,54 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, int max_addrs, | |||
3341 | return cnt; | 3401 | return cnt; |
3342 | } | 3402 | } |
3343 | 3403 | ||
3344 | static int sctp_getsockopt_local_addrs(struct sock *sk, int len, | 3404 | static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, |
3345 | char __user *optval, int __user *optlen) | 3405 | void * __user *to, size_t space_left) |
3406 | { | ||
3407 | struct list_head *pos; | ||
3408 | struct sctp_sockaddr_entry *addr; | ||
3409 | unsigned long flags; | ||
3410 | union sctp_addr temp; | ||
3411 | int cnt = 0; | ||
3412 | int addrlen; | ||
3413 | |||
3414 | sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); | ||
3415 | list_for_each(pos, &sctp_local_addr_list) { | ||
3416 | addr = list_entry(pos, struct sctp_sockaddr_entry, list); | ||
3417 | if ((PF_INET == sk->sk_family) && | ||
3418 | (AF_INET6 == addr->a.sa.sa_family)) | ||
3419 | continue; | ||
3420 | memcpy(&temp, &addr->a, sizeof(temp)); | ||
3421 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), | ||
3422 | &temp); | ||
3423 | addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; | ||
3424 | if(space_left<addrlen) | ||
3425 | return -ENOMEM; | ||
3426 | temp.v4.sin_port = htons(port); | ||
3427 | if (copy_to_user(*to, &temp, addrlen)) { | ||
3428 | sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, | ||
3429 | flags); | ||
3430 | return -EFAULT; | ||
3431 | } | ||
3432 | *to += addrlen; | ||
3433 | cnt ++; | ||
3434 | space_left -= addrlen; | ||
3435 | } | ||
3436 | sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); | ||
3437 | |||
3438 | return cnt; | ||
3439 | } | ||
3440 | |||
3441 | /* Old API for getting list of local addresses. Does not work for 32-bit | ||
3442 | * programs running on a 64-bit kernel | ||
3443 | */ | ||
3444 | static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, | ||
3445 | char __user *optval, int __user *optlen) | ||
3346 | { | 3446 | { |
3347 | struct sctp_bind_addr *bp; | 3447 | struct sctp_bind_addr *bp; |
3348 | struct sctp_association *asoc; | 3448 | struct sctp_association *asoc; |
3349 | struct list_head *pos; | 3449 | struct list_head *pos; |
3350 | int cnt = 0; | 3450 | int cnt = 0; |
3351 | struct sctp_getaddrs getaddrs; | 3451 | struct sctp_getaddrs_old getaddrs; |
3352 | struct sctp_sockaddr_entry *addr; | 3452 | struct sctp_sockaddr_entry *addr; |
3353 | void __user *to; | 3453 | void __user *to; |
3354 | union sctp_addr temp; | 3454 | union sctp_addr temp; |
@@ -3357,10 +3457,10 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, | |||
3357 | rwlock_t *addr_lock; | 3457 | rwlock_t *addr_lock; |
3358 | int err = 0; | 3458 | int err = 0; |
3359 | 3459 | ||
3360 | if (len != sizeof(struct sctp_getaddrs)) | 3460 | if (len != sizeof(struct sctp_getaddrs_old)) |
3361 | return -EINVAL; | 3461 | return -EINVAL; |
3362 | 3462 | ||
3363 | if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) | 3463 | if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old))) |
3364 | return -EFAULT; | 3464 | return -EFAULT; |
3365 | 3465 | ||
3366 | if (getaddrs.addr_num <= 0) return -EINVAL; | 3466 | if (getaddrs.addr_num <= 0) return -EINVAL; |
@@ -3392,8 +3492,9 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, | |||
3392 | addr = list_entry(bp->address_list.next, | 3492 | addr = list_entry(bp->address_list.next, |
3393 | struct sctp_sockaddr_entry, list); | 3493 | struct sctp_sockaddr_entry, list); |
3394 | if (sctp_is_any(&addr->a)) { | 3494 | if (sctp_is_any(&addr->a)) { |
3395 | cnt = sctp_copy_laddrs_to_user(sk, bp->port, | 3495 | cnt = sctp_copy_laddrs_to_user_old(sk, bp->port, |
3396 | getaddrs.addr_num, to); | 3496 | getaddrs.addr_num, |
3497 | to); | ||
3397 | if (cnt < 0) { | 3498 | if (cnt < 0) { |
3398 | err = cnt; | 3499 | err = cnt; |
3399 | goto unlock; | 3500 | goto unlock; |
@@ -3419,7 +3520,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, | |||
3419 | 3520 | ||
3420 | copy_getaddrs: | 3521 | copy_getaddrs: |
3421 | getaddrs.addr_num = cnt; | 3522 | getaddrs.addr_num = cnt; |
3422 | if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs))) | 3523 | if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old))) |
3423 | err = -EFAULT; | 3524 | err = -EFAULT; |
3424 | 3525 | ||
3425 | unlock: | 3526 | unlock: |
@@ -3427,6 +3528,99 @@ unlock: | |||
3427 | return err; | 3528 | return err; |
3428 | } | 3529 | } |
3429 | 3530 | ||
3531 | static int sctp_getsockopt_local_addrs(struct sock *sk, int len, | ||
3532 | char __user *optval, int __user *optlen) | ||
3533 | { | ||
3534 | struct sctp_bind_addr *bp; | ||
3535 | struct sctp_association *asoc; | ||
3536 | struct list_head *pos; | ||
3537 | int cnt = 0; | ||
3538 | struct sctp_getaddrs getaddrs; | ||
3539 | struct sctp_sockaddr_entry *addr; | ||
3540 | void __user *to; | ||
3541 | union sctp_addr temp; | ||
3542 | struct sctp_sock *sp = sctp_sk(sk); | ||
3543 | int addrlen; | ||
3544 | rwlock_t *addr_lock; | ||
3545 | int err = 0; | ||
3546 | size_t space_left; | ||
3547 | int bytes_copied; | ||
3548 | |||
3549 | if (len <= sizeof(struct sctp_getaddrs)) | ||
3550 | return -EINVAL; | ||
3551 | |||
3552 | if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) | ||
3553 | return -EFAULT; | ||
3554 | |||
3555 | /* | ||
3556 | * For UDP-style sockets, id specifies the association to query. | ||
3557 | * If the id field is set to the value '0' then the locally bound | ||
3558 | * addresses are returned without regard to any particular | ||
3559 | * association. | ||
3560 | */ | ||
3561 | if (0 == getaddrs.assoc_id) { | ||
3562 | bp = &sctp_sk(sk)->ep->base.bind_addr; | ||
3563 | addr_lock = &sctp_sk(sk)->ep->base.addr_lock; | ||
3564 | } else { | ||
3565 | asoc = sctp_id2assoc(sk, getaddrs.assoc_id); | ||
3566 | if (!asoc) | ||
3567 | return -EINVAL; | ||
3568 | bp = &asoc->base.bind_addr; | ||
3569 | addr_lock = &asoc->base.addr_lock; | ||
3570 | } | ||
3571 | |||
3572 | to = optval + offsetof(struct sctp_getaddrs,addrs); | ||
3573 | space_left = len - sizeof(struct sctp_getaddrs) - | ||
3574 | offsetof(struct sctp_getaddrs,addrs); | ||
3575 | |||
3576 | sctp_read_lock(addr_lock); | ||
3577 | |||
3578 | /* If the endpoint is bound to 0.0.0.0 or ::0, get the valid | ||
3579 | * addresses from the global local address list. | ||
3580 | */ | ||
3581 | if (sctp_list_single_entry(&bp->address_list)) { | ||
3582 | addr = list_entry(bp->address_list.next, | ||
3583 | struct sctp_sockaddr_entry, list); | ||
3584 | if (sctp_is_any(&addr->a)) { | ||
3585 | cnt = sctp_copy_laddrs_to_user(sk, bp->port, | ||
3586 | &to, space_left); | ||
3587 | if (cnt < 0) { | ||
3588 | err = cnt; | ||
3589 | goto unlock; | ||
3590 | } | ||
3591 | goto copy_getaddrs; | ||
3592 | } | ||
3593 | } | ||
3594 | |||
3595 | list_for_each(pos, &bp->address_list) { | ||
3596 | addr = list_entry(pos, struct sctp_sockaddr_entry, list); | ||
3597 | memcpy(&temp, &addr->a, sizeof(temp)); | ||
3598 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); | ||
3599 | addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; | ||
3600 | if(space_left < addrlen) | ||
3601 | return -ENOMEM; /*fixme: right error?*/ | ||
3602 | temp.v4.sin_port = htons(temp.v4.sin_port); | ||
3603 | if (copy_to_user(to, &temp, addrlen)) { | ||
3604 | err = -EFAULT; | ||
3605 | goto unlock; | ||
3606 | } | ||
3607 | to += addrlen; | ||
3608 | cnt ++; | ||
3609 | space_left -= addrlen; | ||
3610 | } | ||
3611 | |||
3612 | copy_getaddrs: | ||
3613 | if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) | ||
3614 | return -EFAULT; | ||
3615 | bytes_copied = ((char __user *)to) - optval; | ||
3616 | if (put_user(bytes_copied, optlen)) | ||
3617 | return -EFAULT; | ||
3618 | |||
3619 | unlock: | ||
3620 | sctp_read_unlock(addr_lock); | ||
3621 | return err; | ||
3622 | } | ||
3623 | |||
3430 | /* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) | 3624 | /* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) |
3431 | * | 3625 | * |
3432 | * Requests that the local SCTP stack use the enclosed peer address as | 3626 | * 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, | |||
3807 | case SCTP_INITMSG: | 4001 | case SCTP_INITMSG: |
3808 | retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); | 4002 | retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); |
3809 | break; | 4003 | break; |
3810 | case SCTP_GET_PEER_ADDRS_NUM: | 4004 | case SCTP_GET_PEER_ADDRS_NUM_OLD: |
3811 | retval = sctp_getsockopt_peer_addrs_num(sk, len, optval, | 4005 | retval = sctp_getsockopt_peer_addrs_num_old(sk, len, optval, |
4006 | optlen); | ||
4007 | break; | ||
4008 | case SCTP_GET_LOCAL_ADDRS_NUM_OLD: | ||
4009 | retval = sctp_getsockopt_local_addrs_num_old(sk, len, optval, | ||
4010 | optlen); | ||
4011 | break; | ||
4012 | case SCTP_GET_PEER_ADDRS_OLD: | ||
4013 | retval = sctp_getsockopt_peer_addrs_old(sk, len, optval, | ||
3812 | optlen); | 4014 | optlen); |
3813 | break; | 4015 | break; |
3814 | case SCTP_GET_LOCAL_ADDRS_NUM: | 4016 | case SCTP_GET_LOCAL_ADDRS_OLD: |
3815 | retval = sctp_getsockopt_local_addrs_num(sk, len, optval, | 4017 | retval = sctp_getsockopt_local_addrs_old(sk, len, optval, |
3816 | optlen); | 4018 | optlen); |
3817 | break; | 4019 | break; |
3818 | case SCTP_GET_PEER_ADDRS: | 4020 | case SCTP_GET_PEER_ADDRS: |
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 := \ | |||
6 | key.o \ | 6 | key.o \ |
7 | keyring.o \ | 7 | keyring.o \ |
8 | keyctl.o \ | 8 | keyctl.o \ |
9 | permission.o \ | ||
9 | process_keys.o \ | 10 | process_keys.o \ |
10 | request_key.o \ | 11 | request_key.o \ |
11 | request_key_auth.o \ | 12 | 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 @@ | |||
1 | /* permission.c: key permission determination | ||
2 | * | ||
3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include "internal.h" | ||
14 | |||
15 | /*****************************************************************************/ | ||
16 | /* | ||
17 | * check to see whether permission is granted to use a key in the desired way, | ||
18 | * but permit the security modules to override | ||
19 | */ | ||
20 | int key_task_permission(const key_ref_t key_ref, | ||
21 | struct task_struct *context, | ||
22 | key_perm_t perm) | ||
23 | { | ||
24 | struct key *key; | ||
25 | key_perm_t kperm; | ||
26 | int ret; | ||
27 | |||
28 | key = key_ref_to_ptr(key_ref); | ||
29 | |||
30 | /* use the second 8-bits of permissions for keys the caller owns */ | ||
31 | if (key->uid == context->fsuid) { | ||
32 | kperm = key->perm >> 16; | ||
33 | goto use_these_perms; | ||
34 | } | ||
35 | |||
36 | /* use the third 8-bits of permissions for keys the caller has a group | ||
37 | * membership in common with */ | ||
38 | if (key->gid != -1 && key->perm & KEY_GRP_ALL) { | ||
39 | if (key->gid == context->fsgid) { | ||
40 | kperm = key->perm >> 8; | ||
41 | goto use_these_perms; | ||
42 | } | ||
43 | |||
44 | task_lock(context); | ||
45 | ret = groups_search(context->group_info, key->gid); | ||
46 | task_unlock(context); | ||
47 | |||
48 | if (ret) { | ||
49 | kperm = key->perm >> 8; | ||
50 | goto use_these_perms; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | /* otherwise use the least-significant 8-bits */ | ||
55 | kperm = key->perm; | ||
56 | |||
57 | use_these_perms: | ||
58 | /* use the top 8-bits of permissions for keys the caller possesses | ||
59 | * - possessor permissions are additive with other permissions | ||
60 | */ | ||
61 | if (is_key_possessed(key_ref)) | ||
62 | kperm |= key->perm >> 24; | ||
63 | |||
64 | kperm = kperm & perm & KEY_ALL; | ||
65 | |||
66 | return kperm == perm; | ||
67 | |||
68 | } /* end key_task_permission() */ | ||
69 | |||
70 | 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 @@ | |||
7 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
8 | * as published by the Free Software Foundation; either version | 8 | * as published by the Free Software Foundation; either version |
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | * | ||
11 | * See Documentation/keys-request-key.txt | ||
10 | */ | 12 | */ |
11 | 13 | ||
12 | #include <linux/module.h> | 14 | #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 @@ | |||
7 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
8 | * as published by the Free Software Foundation; either version | 8 | * as published by the Free Software Foundation; either version |
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | * | ||
11 | * See Documentation/keys-request-key.txt | ||
10 | */ | 12 | */ |
11 | 13 | ||
12 | #include <linux/module.h> | 14 | #include <linux/module.h> |
@@ -96,6 +98,7 @@ static void request_key_auth_destroy(struct key *key) | |||
96 | kenter("{%d}", key->serial); | 98 | kenter("{%d}", key->serial); |
97 | 99 | ||
98 | key_put(rka->target_key); | 100 | key_put(rka->target_key); |
101 | kfree(rka); | ||
99 | 102 | ||
100 | } /* end request_key_auth_destroy() */ | 103 | } /* end request_key_auth_destroy() */ |
101 | 104 | ||