Print this page
8634 epoll fails to wake on certain edge-triggered conditions
8635 epoll should not emit POLLNVAL
8636 recursive epoll should emit EPOLLRDNORM
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Igor Kozhukhov <igor@dilos.org>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/random.c
+++ new/usr/src/uts/common/io/random.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 *
21 21 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
22 22 * Use is subject to license terms.
23 + *
24 + * Copyright 2017 Joyent, Inc.
23 25 */
24 26
25 27
26 28 /*
27 29 * Random number generator pseudo-driver
28 30 *
29 31 * This is a lightweight driver which calls in to the Kernel Cryptographic
30 32 * Framework to do the real work. Kernel modules should NOT depend on this
31 33 * driver for /dev/random kernel API.
32 34 *
33 35 * Applications may ask for 2 types of random bits:
34 36 * . High quality random by reading from /dev/random. The output is extracted
35 37 * only when a minimum amount of entropy is available.
36 38 * . Pseudo-random, by reading from /dev/urandom, that can be generated any
37 39 * time.
38 40 */
39 41
40 42 #include <sys/types.h>
41 43 #include <sys/errno.h>
42 44 #include <sys/stat.h>
43 45
44 46 #include <sys/file.h>
45 47 #include <sys/open.h>
46 48 #include <sys/poll.h>
47 49 #include <sys/uio.h>
48 50 #include <sys/cred.h>
49 51 #include <sys/modctl.h>
50 52 #include <sys/conf.h>
51 53 #include <sys/ddi.h>
52 54 #include <sys/sunddi.h>
53 55 #include <sys/random.h>
54 56 #include <sys/crypto/impl.h>
55 57
56 58 #define DEVRANDOM 0
57 59 #define DEVURANDOM 1
58 60
59 61 #define HASHSIZE 20 /* Assuming a SHA1 hash algorithm */
60 62 #define WRITEBUFSIZE 512 /* Size of buffer for write request */
61 63 #define MAXRETBYTES 1040 /* Max bytes returned per read. */
62 64 /* Must be a multiple of HASHSIZE */
63 65 static dev_info_t *rnd_dip;
64 66
65 67 static int rnd_open(dev_t *, int, int, cred_t *);
66 68 static int rnd_close(dev_t, int, int, cred_t *);
67 69 static int rnd_read(dev_t, struct uio *, cred_t *);
68 70 static int rnd_write(dev_t, struct uio *, cred_t *);
69 71 static int rnd_chpoll(dev_t, short, int, short *, struct pollhead **);
70 72 static int rnd_attach(dev_info_t *, ddi_attach_cmd_t);
71 73 static int rnd_detach(dev_info_t *, ddi_detach_cmd_t);
72 74 static int rnd_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
73 75
74 76 /* DDI declarations */
75 77 static struct cb_ops rnd_cb_ops = {
76 78 rnd_open, /* open */
77 79 rnd_close, /* close */
78 80 nodev, /* strategy */
79 81 nodev, /* print */
80 82 nodev, /* dump */
81 83 rnd_read, /* read */
82 84 rnd_write, /* write */
83 85 nodev, /* ioctl */
84 86 nodev, /* devmap */
85 87 nodev, /* mmap */
86 88 nodev, /* segmap */
87 89 rnd_chpoll, /* chpoll */
88 90 ddi_prop_op, /* prop_op */
89 91 NULL, /* streamtab */
90 92 (D_NEW | D_MP), /* cb_flag */
91 93 CB_REV, /* cb_rev */
92 94 nodev, /* aread */
93 95 nodev /* awrite */
94 96 };
95 97
96 98 static struct dev_ops rnd_ops = {
97 99 DEVO_REV, /* devo_rev, */
98 100 0, /* refcnt */
99 101 rnd_getinfo, /* get_dev_info */
100 102 nulldev, /* identify */
101 103 nulldev, /* probe */
102 104 rnd_attach, /* attach */
103 105 rnd_detach, /* detach */
104 106 nodev, /* reset */
105 107 &rnd_cb_ops, /* driver operations */
106 108 NULL, /* bus operations */
107 109 NULL, /* power */
108 110 ddi_quiesce_not_needed, /* quiesce */
109 111 };
110 112
111 113 /* Modlinkage */
112 114 static struct modldrv modldrv = {
113 115 &mod_driverops,
114 116 "random number device",
115 117 &rnd_ops
116 118 };
117 119
118 120 static struct modlinkage modlinkage = { MODREV_1, { &modldrv, NULL } };
119 121
120 122
121 123 /* DDI glue */
122 124
123 125 int
124 126 _init(void)
125 127 {
126 128 return (mod_install(&modlinkage));
127 129 }
128 130
129 131 int
130 132 _fini(void)
131 133 {
132 134 return (mod_remove(&modlinkage));
133 135 }
134 136
135 137 int
136 138 _info(struct modinfo *modinfop)
137 139 {
138 140 return (mod_info(&modlinkage, modinfop));
139 141 }
140 142
141 143 static int
142 144 rnd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
143 145 {
144 146 if (cmd != DDI_ATTACH)
145 147 return (DDI_FAILURE);
146 148
147 149 if (ddi_create_minor_node(dip, "random", S_IFCHR, DEVRANDOM,
148 150 DDI_PSEUDO, 0) == DDI_FAILURE) {
149 151 ddi_remove_minor_node(dip, NULL);
150 152 return (DDI_FAILURE);
151 153 }
152 154 if (ddi_create_minor_node(dip, "urandom", S_IFCHR, DEVURANDOM,
153 155 DDI_PSEUDO, 0) == DDI_FAILURE) {
154 156 ddi_remove_minor_node(dip, NULL);
155 157 return (DDI_FAILURE);
156 158 }
157 159
158 160 rnd_dip = dip;
159 161
160 162 return (DDI_SUCCESS);
161 163 }
162 164
163 165 static int
164 166 rnd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
165 167 {
166 168 if (cmd != DDI_DETACH)
167 169 return (DDI_FAILURE);
168 170
169 171 rnd_dip = NULL;
170 172 ddi_remove_minor_node(dip, NULL);
171 173
172 174 return (DDI_SUCCESS);
173 175 }
174 176
175 177 /*ARGSUSED*/
176 178 static int
177 179 rnd_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
178 180 {
179 181 int error;
180 182
181 183 switch (infocmd) {
182 184 case DDI_INFO_DEVT2DEVINFO:
183 185 *result = rnd_dip;
184 186 error = DDI_SUCCESS;
185 187 break;
186 188 case DDI_INFO_DEVT2INSTANCE:
187 189 *result = (void *)0;
188 190 error = DDI_SUCCESS;
189 191 break;
190 192 default:
191 193 error = DDI_FAILURE;
192 194 }
193 195 return (error);
194 196 }
195 197
196 198 /*ARGSUSED3*/
197 199 static int
198 200 rnd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
199 201 {
200 202 switch (getminor(*devp)) {
201 203 case DEVRANDOM:
202 204 if (!kcf_rngprov_check())
203 205 return (ENXIO);
204 206 break;
205 207 case DEVURANDOM:
206 208 break;
207 209 default:
208 210 return (ENXIO);
209 211 }
210 212 if (otyp != OTYP_CHR)
211 213 return (EINVAL);
212 214
213 215 if (flag & FEXCL)
214 216 return (EINVAL);
215 217 return (0);
216 218 }
217 219
218 220 /*ARGSUSED*/
219 221 static int
220 222 rnd_close(dev_t dev, int flag, int otyp, cred_t *credp)
221 223 {
222 224 return (0);
223 225 }
224 226
225 227 /*ARGSUSED2*/
226 228 static int
227 229 rnd_read(dev_t dev, struct uio *uiop, cred_t *credp)
228 230 {
229 231 size_t len;
230 232 minor_t devno;
231 233 int error = 0;
232 234 int nbytes = 0;
233 235 uint8_t random_bytes[2 * HASHSIZE];
234 236
235 237 devno = getminor(dev);
236 238
237 239 while (error == 0 && uiop->uio_resid > 0) {
238 240 len = min(sizeof (random_bytes), uiop->uio_resid);
239 241 switch (devno) {
240 242 case DEVRANDOM:
241 243 error = kcf_rnd_get_bytes(random_bytes, len,
242 244 uiop->uio_fmode & (FNDELAY|FNONBLOCK));
243 245 break;
244 246 case DEVURANDOM:
245 247 error = kcf_rnd_get_pseudo_bytes(random_bytes, len);
246 248 break;
247 249 default:
248 250 return (ENXIO);
249 251 }
250 252
251 253 if (error == 0) {
252 254 /*
253 255 * /dev/[u]random is not a seekable device. To prevent
254 256 * uio offset from growing and eventually exceeding
255 257 * the maximum, reset the offset here for every call.
256 258 */
257 259 uiop->uio_loffset = 0;
258 260 error = uiomove(random_bytes, len, UIO_READ, uiop);
259 261
260 262 nbytes += len;
261 263
262 264 if (devno == DEVRANDOM && nbytes >= MAXRETBYTES)
263 265 break;
264 266
265 267 } else if ((error == EAGAIN) && (nbytes > 0)) {
266 268 error = 0;
267 269 break;
268 270 }
269 271 }
270 272 return (error);
271 273 }
272 274
273 275 /*ARGSUSED*/
274 276 static int
275 277 rnd_write(dev_t dev, struct uio *uiop, cred_t *credp)
276 278 {
277 279 int error;
278 280 uint8_t buf[WRITEBUFSIZE];
279 281 size_t bytes;
280 282 minor_t devno;
281 283
282 284 devno = getminor(dev);
283 285
284 286 while (uiop->uio_resid > 0) {
285 287 bytes = min(sizeof (buf), uiop->uio_resid);
286 288
287 289 /* See comments in rnd_read() */
288 290 uiop->uio_loffset = 0;
289 291 if ((error = uiomove(buf, bytes, UIO_WRITE, uiop)) != 0)
290 292 return (error);
291 293
292 294 switch (devno) {
293 295 case DEVRANDOM:
294 296 if ((error = random_add_entropy(buf, bytes, 0)) != 0)
295 297 return (error);
296 298 break;
297 299 case DEVURANDOM:
298 300 if ((error = random_add_pseudo_entropy(buf, bytes,
299 301 0)) != 0)
300 302 return (error);
301 303 break;
302 304 default:
303 305 return (ENXIO);
304 306 }
305 307 }
306 308
307 309 return (0);
308 310 }
309 311
310 312 static struct pollhead urnd_pollhd;
311 313
312 314 /*
313 315 * poll(2) is supported as follows:
314 316 * . Only POLLIN, POLLOUT, and POLLRDNORM events are supported.
315 317 * . POLLOUT always succeeds.
316 318 * . POLLIN and POLLRDNORM from /dev/urandom always succeeds.
317 319 * . POLLIN and POLLRDNORM from /dev/random will block until a
318 320 * minimum amount of entropy is available.
319 321 */
320 322 static int
321 323 rnd_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
|
↓ open down ↓ |
289 lines elided |
↑ open up ↑ |
322 324 struct pollhead **phpp)
323 325 {
324 326 switch (getminor(dev)) {
325 327 case DEVURANDOM:
326 328 *reventsp = events & (POLLOUT | POLLIN | POLLRDNORM);
327 329
328 330 /*
329 331 * A non NULL pollhead pointer should be returned in case
330 332 * user polls for 0 events.
331 333 */
332 - if (*reventsp == 0 && !anyyet)
334 + if ((*reventsp == 0 && !anyyet) || (events & POLLET))
333 335 *phpp = &urnd_pollhd;
334 336
335 337 break;
336 338 case DEVRANDOM:
337 339 kcf_rnd_chpoll(events, anyyet, reventsp, phpp);
338 340 break;
339 341 default:
340 342 return (ENXIO);
341 343 }
342 344
343 345 return (0);
344 346 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX