1 /*-
2 * Copyright (c) 1998 Mark Newton
3 * Copyright (c) 1994, 1997 Christos Zoulas.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Christos Zoulas.
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD: releng/8.0/sys/compat/svr4/svr4_fcntl.c 193511 2009-06-05 14:55:22Z rwatson $");
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/file.h>
38 #include <sys/filedesc.h>
39 /*#include <sys/ioctl.h>*/
40 #include <sys/lock.h>
41 #include <sys/malloc.h>
42 #include <sys/mount.h>
43 #include <sys/mutex.h>
44 #include <sys/namei.h>
45 #include <sys/priv.h>
46 #include <sys/proc.h>
47 #include <sys/stat.h>
48 #include <sys/syscallsubr.h>
49 #include <sys/unistd.h>
50 #include <sys/vnode.h>
51
52 #include <sys/sysproto.h>
53
54 #include <compat/svr4/svr4.h>
55 #include <compat/svr4/svr4_types.h>
56 #include <compat/svr4/svr4_signal.h>
57 #include <compat/svr4/svr4_proto.h>
58 #include <compat/svr4/svr4_util.h>
59 #include <compat/svr4/svr4_fcntl.h>
60
61 #include <security/mac/mac_framework.h>
62
63 static int svr4_to_bsd_flags(int);
64 static u_long svr4_to_bsd_cmd(u_long);
65 static int fd_revoke(struct thread *, int);
66 static int fd_truncate(struct thread *, int, struct flock *);
67 static int bsd_to_svr4_flags(int);
68 static void bsd_to_svr4_flock(struct flock *, struct svr4_flock *);
69 static void svr4_to_bsd_flock(struct svr4_flock *, struct flock *);
70 static void bsd_to_svr4_flock64(struct flock *, struct svr4_flock64 *);
71 static void svr4_to_bsd_flock64(struct svr4_flock64 *, struct flock *);
72
73 static u_long
74 svr4_to_bsd_cmd(cmd)
75 u_long cmd;
76 {
77 switch (cmd) {
78 case SVR4_F_DUPFD:
79 return F_DUPFD;
80 case SVR4_F_DUP2FD:
81 return F_DUP2FD;
82 case SVR4_F_GETFD:
83 return F_GETFD;
84 case SVR4_F_SETFD:
85 return F_SETFD;
86 case SVR4_F_GETFL:
87 return F_GETFL;
88 case SVR4_F_SETFL:
89 return F_SETFL;
90 case SVR4_F_GETLK:
91 return F_GETLK;
92 case SVR4_F_SETLK:
93 return F_SETLK;
94 case SVR4_F_SETLKW:
95 return F_SETLKW;
96 default:
97 return -1;
98 }
99 }
100
101 static int
102 svr4_to_bsd_flags(l)
103 int l;
104 {
105 int r = 0;
106 r |= (l & SVR4_O_RDONLY) ? O_RDONLY : 0;
107 r |= (l & SVR4_O_WRONLY) ? O_WRONLY : 0;
108 r |= (l & SVR4_O_RDWR) ? O_RDWR : 0;
109 r |= (l & SVR4_O_NDELAY) ? O_NONBLOCK : 0;
110 r |= (l & SVR4_O_APPEND) ? O_APPEND : 0;
111 r |= (l & SVR4_O_SYNC) ? O_FSYNC : 0;
112 r |= (l & SVR4_O_NONBLOCK) ? O_NONBLOCK : 0;
113 r |= (l & SVR4_O_PRIV) ? O_EXLOCK : 0;
114 r |= (l & SVR4_O_CREAT) ? O_CREAT : 0;
115 r |= (l & SVR4_O_TRUNC) ? O_TRUNC : 0;
116 r |= (l & SVR4_O_EXCL) ? O_EXCL : 0;
117 r |= (l & SVR4_O_NOCTTY) ? O_NOCTTY : 0;
118 return r;
119 }
120
121 static int
122 bsd_to_svr4_flags(l)
123 int l;
124 {
125 int r = 0;
126 r |= (l & O_RDONLY) ? SVR4_O_RDONLY : 0;
127 r |= (l & O_WRONLY) ? SVR4_O_WRONLY : 0;
128 r |= (l & O_RDWR) ? SVR4_O_RDWR : 0;
129 r |= (l & O_NDELAY) ? SVR4_O_NONBLOCK : 0;
130 r |= (l & O_APPEND) ? SVR4_O_APPEND : 0;
131 r |= (l & O_FSYNC) ? SVR4_O_SYNC : 0;
132 r |= (l & O_NONBLOCK) ? SVR4_O_NONBLOCK : 0;
133 r |= (l & O_EXLOCK) ? SVR4_O_PRIV : 0;
134 r |= (l & O_CREAT) ? SVR4_O_CREAT : 0;
135 r |= (l & O_TRUNC) ? SVR4_O_TRUNC : 0;
136 r |= (l & O_EXCL) ? SVR4_O_EXCL : 0;
137 r |= (l & O_NOCTTY) ? SVR4_O_NOCTTY : 0;
138 return r;
139 }
140
141
142 static void
143 bsd_to_svr4_flock(iflp, oflp)
144 struct flock *iflp;
145 struct svr4_flock *oflp;
146 {
147 switch (iflp->l_type) {
148 case F_RDLCK:
149 oflp->l_type = SVR4_F_RDLCK;
150 break;
151 case F_WRLCK:
152 oflp->l_type = SVR4_F_WRLCK;
153 break;
154 case F_UNLCK:
155 oflp->l_type = SVR4_F_UNLCK;
156 break;
157 default:
158 oflp->l_type = -1;
159 break;
160 }
161
162 oflp->l_whence = (short) iflp->l_whence;
163 oflp->l_start = (svr4_off_t) iflp->l_start;
164 oflp->l_len = (svr4_off_t) iflp->l_len;
165 oflp->l_sysid = 0;
166 oflp->l_pid = (svr4_pid_t) iflp->l_pid;
167 }
168
169
170 static void
171 svr4_to_bsd_flock(iflp, oflp)
172 struct svr4_flock *iflp;
173 struct flock *oflp;
174 {
175 switch (iflp->l_type) {
176 case SVR4_F_RDLCK:
177 oflp->l_type = F_RDLCK;
178 break;
179 case SVR4_F_WRLCK:
180 oflp->l_type = F_WRLCK;
181 break;
182 case SVR4_F_UNLCK:
183 oflp->l_type = F_UNLCK;
184 break;
185 default:
186 oflp->l_type = -1;
187 break;
188 }
189
190 oflp->l_whence = iflp->l_whence;
191 oflp->l_start = (off_t) iflp->l_start;
192 oflp->l_len = (off_t) iflp->l_len;
193 oflp->l_pid = (pid_t) iflp->l_pid;
194 oflp->l_sysid = iflp->l_sysid;
195 }
196
197 static void
198 bsd_to_svr4_flock64(iflp, oflp)
199 struct flock *iflp;
200 struct svr4_flock64 *oflp;
201 {
202 switch (iflp->l_type) {
203 case F_RDLCK:
204 oflp->l_type = SVR4_F_RDLCK;
205 break;
206 case F_WRLCK:
207 oflp->l_type = SVR4_F_WRLCK;
208 break;
209 case F_UNLCK:
210 oflp->l_type = SVR4_F_UNLCK;
211 break;
212 default:
213 oflp->l_type = -1;
214 break;
215 }
216
217 oflp->l_whence = (short) iflp->l_whence;
218 oflp->l_start = (svr4_off64_t) iflp->l_start;
219 oflp->l_len = (svr4_off64_t) iflp->l_len;
220 oflp->l_sysid = iflp->l_sysid;
221 oflp->l_pid = (svr4_pid_t) iflp->l_pid;
222 }
223
224
225 static void
226 svr4_to_bsd_flock64(iflp, oflp)
227 struct svr4_flock64 *iflp;
228 struct flock *oflp;
229 {
230 switch (iflp->l_type) {
231 case SVR4_F_RDLCK:
232 oflp->l_type = F_RDLCK;
233 break;
234 case SVR4_F_WRLCK:
235 oflp->l_type = F_WRLCK;
236 break;
237 case SVR4_F_UNLCK:
238 oflp->l_type = F_UNLCK;
239 break;
240 default:
241 oflp->l_type = -1;
242 break;
243 }
244
245 oflp->l_whence = iflp->l_whence;
246 oflp->l_start = (off_t) iflp->l_start;
247 oflp->l_len = (off_t) iflp->l_len;
248 oflp->l_pid = (pid_t) iflp->l_pid;
249
250 }
251
252
253 static int
254 fd_revoke(td, fd)
255 struct thread *td;
256 int fd;
257 {
258 struct vnode *vp;
259 struct mount *mp;
260 struct vattr vattr;
261 int error, *retval;
262
263 retval = td->td_retval;
264 if ((error = fgetvp(td, fd, &vp)) != 0)
265 return (error);
266
267 if (vp->v_type != VCHR && vp->v_type != VBLK) {
268 error = EINVAL;
269 goto out;
270 }
271
272 #ifdef MAC
273 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
274 error = mac_vnode_check_revoke(td->td_ucred, vp);
275 VOP_UNLOCK(vp, 0);
276 if (error)
277 goto out;
278 #endif
279
280 if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred)) != 0)
281 goto out;
282
283 if (td->td_ucred->cr_uid != vattr.va_uid &&
284 (error = priv_check(td, PRIV_VFS_ADMIN)) != 0)
285 goto out;
286
287 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
288 goto out;
289 if (vcount(vp) > 1)
290 VOP_REVOKE(vp, REVOKEALL);
291 vn_finished_write(mp);
292 out:
293 vrele(vp);
294 return error;
295 }
296
297
298 static int
299 fd_truncate(td, fd, flp)
300 struct thread *td;
301 int fd;
302 struct flock *flp;
303 {
304 off_t start, length;
305 struct file *fp;
306 struct vnode *vp;
307 struct vattr vattr;
308 int error, *retval;
309 struct ftruncate_args ft;
310
311 retval = td->td_retval;
312
313 /*
314 * We only support truncating the file.
315 */
316 if ((error = fget(td, fd, &fp)) != 0)
317 return (error);
318
319 vp = fp->f_vnode;
320
321 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
322 fdrop(fp, td);
323 return ESPIPE;
324 }
325
326 if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred)) != 0) {
327 fdrop(fp, td);
328 return error;
329 }
330
331 length = vattr.va_size;
332
333 switch (flp->l_whence) {
334 case SEEK_CUR:
335 start = fp->f_offset + flp->l_start;
336 break;
337
338 case SEEK_END:
339 start = flp->l_start + length;
340 break;
341
342 case SEEK_SET:
343 start = flp->l_start;
344 break;
345
346 default:
347 fdrop(fp, td);
348 return EINVAL;
349 }
350
351 if (start + flp->l_len < length) {
352 /* We don't support free'ing in the middle of the file */
353 fdrop(fp, td);
354 return EINVAL;
355 }
356
357 ft.fd = fd;
358 ft.length = start;
359
360 error = ftruncate(td, &ft);
361
362 fdrop(fp, td);
363 return (error);
364 }
365
366 int
367 svr4_sys_open(td, uap)
368 struct thread *td;
369 struct svr4_sys_open_args *uap;
370 {
371 struct proc *p = td->td_proc;
372 char *newpath;
373 int bsd_flags, error, retval;
374
375 CHECKALTEXIST(td, uap->path, &newpath);
376
377 bsd_flags = svr4_to_bsd_flags(uap->flags);
378 error = kern_open(td, newpath, UIO_SYSSPACE, bsd_flags, uap->mode);
379 free(newpath, M_TEMP);
380
381 if (error) {
382 /* uprintf("svr4_open(%s, 0x%0x, 0%o): %d\n", uap->path,
383 uap->flags, uap->mode, error);*/
384 return error;
385 }
386
387 retval = td->td_retval[0];
388
389 PROC_LOCK(p);
390 if (!(bsd_flags & O_NOCTTY) && SESS_LEADER(p) &&
391 !(p->p_flag & P_CONTROLT)) {
392 #if defined(NOTYET)
393 struct file *fp;
394
395 error = fget(td, retval, &fp);
396 PROC_UNLOCK(p);
397 /*
398 * we may have lost a race the above open() and
399 * another thread issuing a close()
400 */
401 if (error)
402 return (EBADF); /* XXX: correct errno? */
403 /* ignore any error, just give it a try */
404 if (fp->f_type == DTYPE_VNODE)
405 fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred,
406 td);
407 fdrop(fp, td);
408 } else {
409 PROC_UNLOCK(p);
410 }
411 #else
412 }
413 PROC_UNLOCK(p);
414 #endif
415 return error;
416 }
417
418 int
419 svr4_sys_open64(td, uap)
420 struct thread *td;
421 struct svr4_sys_open64_args *uap;
422 {
423 return svr4_sys_open(td, (struct svr4_sys_open_args *)uap);
424 }
425
426 int
427 svr4_sys_creat(td, uap)
428 struct thread *td;
429 struct svr4_sys_creat_args *uap;
430 {
431 char *newpath;
432 int error;
433
434 CHECKALTEXIST(td, uap->path, &newpath);
435
436 error = kern_open(td, newpath, UIO_SYSSPACE, O_WRONLY | O_CREAT |
437 O_TRUNC, uap->mode);
438 free(newpath, M_TEMP);
439 return (error);
440 }
441
442 int
443 svr4_sys_creat64(td, uap)
444 struct thread *td;
445 struct svr4_sys_creat64_args *uap;
446 {
447 return svr4_sys_creat(td, (struct svr4_sys_creat_args *)uap);
448 }
449
450 int
451 svr4_sys_llseek(td, uap)
452 struct thread *td;
453 struct svr4_sys_llseek_args *uap;
454 {
455 struct lseek_args ap;
456
457 ap.fd = uap->fd;
458
459 #if BYTE_ORDER == BIG_ENDIAN
460 ap.offset = (((u_int64_t) uap->offset1) << 32) |
461 uap->offset2;
462 #else
463 ap.offset = (((u_int64_t) uap->offset2) << 32) |
464 uap->offset1;
465 #endif
466 ap.whence = uap->whence;
467
468 return lseek(td, &ap);
469 }
470
471 int
472 svr4_sys_access(td, uap)
473 struct thread *td;
474 struct svr4_sys_access_args *uap;
475 {
476 char *newpath;
477 int error;
478
479 CHECKALTEXIST(td, uap->path, &newpath);
480 error = kern_access(td, newpath, UIO_SYSSPACE, uap->flags);
481 free(newpath, M_TEMP);
482 return (error);
483 }
484
485 #if defined(NOTYET)
486 int
487 svr4_sys_pread(td, uap)
488 struct thread *td;
489 struct svr4_sys_pread_args *uap;
490 {
491 struct pread_args pra;
492
493 /*
494 * Just translate the args structure and call the NetBSD
495 * pread(2) system call (offset type is 64-bit in NetBSD).
496 */
497 pra.fd = uap->fd;
498 pra.buf = uap->buf;
499 pra.nbyte = uap->nbyte;
500 pra.offset = uap->off;
501
502 return pread(td, &pra);
503 }
504 #endif
505
506 #if defined(NOTYET)
507 int
508 svr4_sys_pread64(td, v, retval)
509 struct thread *td;
510 void *v;
511 register_t *retval;
512 {
513
514 struct svr4_sys_pread64_args *uap = v;
515 struct sys_pread_args pra;
516
517 /*
518 * Just translate the args structure and call the NetBSD
519 * pread(2) system call (offset type is 64-bit in NetBSD).
520 */
521 pra.fd = uap->fd;
522 pra.buf = uap->buf;
523 pra.nbyte = uap->nbyte;
524 pra.offset = uap->off;
525
526 return (sys_pread(td, &pra, retval));
527 }
528 #endif /* NOTYET */
529
530 #if defined(NOTYET)
531 int
532 svr4_sys_pwrite(td, uap)
533 struct thread *td;
534 struct svr4_sys_pwrite_args *uap;
535 {
536 struct pwrite_args pwa;
537
538 /*
539 * Just translate the args structure and call the NetBSD
540 * pwrite(2) system call (offset type is 64-bit in NetBSD).
541 */
542 pwa.fd = uap->fd;
543 pwa.buf = uap->buf;
544 pwa.nbyte = uap->nbyte;
545 pwa.offset = uap->off;
546
547 return pwrite(td, &pwa);
548 }
549 #endif
550
551 #if defined(NOTYET)
552 int
553 svr4_sys_pwrite64(td, v, retval)
554 struct thread *td;
555 void *v;
556 register_t *retval;
557 {
558 struct svr4_sys_pwrite64_args *uap = v;
559 struct sys_pwrite_args pwa;
560
561 /*
562 * Just translate the args structure and call the NetBSD
563 * pwrite(2) system call (offset type is 64-bit in NetBSD).
564 */
565 pwa.fd = uap->fd;
566 pwa.buf = uap->buf;
567 pwa.nbyte = uap->nbyte;
568 pwa.offset = uap->off;
569
570 return (sys_pwrite(td, &pwa, retval));
571 }
572 #endif /* NOTYET */
573
574 int
575 svr4_sys_fcntl(td, uap)
576 struct thread *td;
577 struct svr4_sys_fcntl_args *uap;
578 {
579 int cmd, error, *retval;
580
581 retval = td->td_retval;
582
583 cmd = svr4_to_bsd_cmd(uap->cmd);
584
585 switch (cmd) {
586 case F_DUPFD:
587 case F_DUP2FD:
588 case F_GETFD:
589 case F_SETFD:
590 return (kern_fcntl(td, uap->fd, cmd, (intptr_t)uap->arg));
591
592 case F_GETFL:
593 error = kern_fcntl(td, uap->fd, cmd, (intptr_t)uap->arg);
594 if (error)
595 return (error);
596 *retval = bsd_to_svr4_flags(*retval);
597 return (error);
598
599 case F_SETFL:
600 {
601 /*
602 * we must save the O_ASYNC flag, as that is
603 * handled by ioctl(_, I_SETSIG, _) emulation.
604 */
605 int flags;
606
607 DPRINTF(("Setting flags %p\n", uap->arg));
608
609 error = kern_fcntl(td, uap->fd, F_GETFL, 0);
610 if (error)
611 return (error);
612 flags = *retval;
613 flags &= O_ASYNC;
614 flags |= svr4_to_bsd_flags((u_long) uap->arg);
615 return (kern_fcntl(td, uap->fd, F_SETFL, flags));
616 }
617
618 case F_GETLK:
619 case F_SETLK:
620 case F_SETLKW:
621 {
622 struct svr4_flock ifl;
623 struct flock fl;
624
625 error = copyin(uap->arg, &ifl, sizeof (ifl));
626 if (error)
627 return (error);
628
629 svr4_to_bsd_flock(&ifl, &fl);
630
631 error = kern_fcntl(td, uap->fd, cmd, (intptr_t)&fl);
632 if (error || cmd != F_GETLK)
633 return (error);
634
635 bsd_to_svr4_flock(&fl, &ifl);
636
637 return (copyout(&ifl, uap->arg, sizeof (ifl)));
638 }
639 case -1:
640 switch (uap->cmd) {
641 case SVR4_F_FREESP:
642 {
643 struct svr4_flock ifl;
644 struct flock fl;
645
646 error = copyin(uap->arg, &ifl,
647 sizeof ifl);
648 if (error)
649 return error;
650 svr4_to_bsd_flock(&ifl, &fl);
651 return fd_truncate(td, uap->fd, &fl);
652 }
653
654 case SVR4_F_GETLK64:
655 case SVR4_F_SETLK64:
656 case SVR4_F_SETLKW64:
657 {
658 struct svr4_flock64 ifl;
659 struct flock fl;
660
661 switch (uap->cmd) {
662 case SVR4_F_GETLK64:
663 cmd = F_GETLK;
664 break;
665 case SVR4_F_SETLK64:
666 cmd = F_SETLK;
667 break;
668 case SVR4_F_SETLKW64:
669 cmd = F_SETLKW;
670 break;
671 }
672 error = copyin(uap->arg, &ifl,
673 sizeof (ifl));
674 if (error)
675 return (error);
676
677 svr4_to_bsd_flock64(&ifl, &fl);
678
679 error = kern_fcntl(td, uap->fd, cmd,
680 (intptr_t)&fl);
681 if (error || cmd != F_GETLK)
682 return (error);
683
684 bsd_to_svr4_flock64(&fl, &ifl);
685
686 return (copyout(&ifl, uap->arg,
687 sizeof (ifl)));
688 }
689
690 case SVR4_F_FREESP64:
691 {
692 struct svr4_flock64 ifl;
693 struct flock fl;
694
695 error = copyin(uap->arg, &ifl,
696 sizeof ifl);
697 if (error)
698 return error;
699 svr4_to_bsd_flock64(&ifl, &fl);
700 return fd_truncate(td, uap->fd, &fl);
701 }
702
703 case SVR4_F_REVOKE:
704 return fd_revoke(td, uap->fd);
705
706 default:
707 return ENOSYS;
708 }
709
710 default:
711 return ENOSYS;
712 }
713 }
Cache object: d778aa65fe8b584ebee08a34281c7ad3
|