diff options
author | netchild <netchild@FreeBSD.org> | 2006-09-23 19:06:54 +0000 |
---|---|---|
committer | netchild <netchild@FreeBSD.org> | 2006-09-23 19:06:54 +0000 |
commit | 6ecb474f4fee36803a21cadcee5dc0f6b0e6b4d2 (patch) | |
tree | 7a35442ca35fbab402321b222ccf332ac2aa2150 | |
parent | 39ac06be39bc2d3437458d0d947516526772cffb (diff) | |
download | FreeBSD-src-6ecb474f4fee36803a21cadcee5dc0f6b0e6b4d2.zip FreeBSD-src-6ecb474f4fee36803a21cadcee5dc0f6b0e6b4d2.tar.gz |
MFp4:
- Linux returns ENOPROTOOPT in a case of not supported opt to setsockopt.
- Return EISDIR in pread() when arg is a directory.
- Return EINVAL instead of EFAULT when namelen is not correct in accept().
- Return EINVAL instead of EACCESS if invalid access mode is entered in
access().
- Return EINVAL instead of EADDRNOTAVAIL in a case of bad salen param
to bind().
Submitted by: rdivacky
Tested with: LTP (vfork01 fails now, but it seems to be a race and
not caused by those changes)
MFC after: 1 week
-rw-r--r-- | sys/compat/linux/linux_file.c | 24 | ||||
-rw-r--r-- | sys/compat/linux/linux_socket.c | 9 |
2 files changed, 30 insertions, 3 deletions
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 327f604..185ca5c 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <sys/syscallsubr.h> #include <sys/sysproto.h> #include <sys/tty.h> +#include <sys/unistd.h> #include <sys/vnode.h> #include <ufs/ufs/extattr.h> @@ -480,6 +481,10 @@ linux_access(struct thread *td, struct linux_access_args *args) char *path; int error; + /* linux convention */ + if (args->flags & ~(F_OK | X_OK | W_OK | R_OK)) + return (EINVAL); + LCONVPATHEXIST(td, args->path, &path); #ifdef DEBUG @@ -488,6 +493,7 @@ linux_access(struct thread *td, struct linux_access_args *args) #endif error = kern_access(td, path, UIO_SYSSPACE, args->flags); LFREEPATH(path); + return (error); } @@ -724,12 +730,28 @@ linux_pread(td, uap) struct linux_pread_args *uap; { struct pread_args bsd; + struct vnode *vp; + int error; bsd.fd = uap->fd; bsd.buf = uap->buf; bsd.nbyte = uap->nbyte; bsd.offset = uap->offset; - return pread(td, &bsd); + + error = pread(td, &bsd); + + if (error == 0) { + /* This seems to violate POSIX but linux does it */ + if ((error = fgetvp(td, uap->fd, &vp)) != 0) + return (error); + if (vp->v_type == VDIR) { + vrele(vp); + return (EISDIR); + } + vrele(vp); + } + + return (error); } int diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index 3f089c0..174fba6 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -611,6 +611,8 @@ linux_bind(struct thread *td, struct linux_bind_args *args) error = kern_bind(td, linux_args.s, sa); free(sa, M_SONAME); + if (error == EADDRNOTAVAIL && linux_args.namelen != sizeof(struct sockaddr_in)) + return (EINVAL); return (error); } @@ -719,8 +721,11 @@ linux_accept(struct thread *td, struct linux_accept_args *args) bsd_args.anamelen = PTRIN(linux_args.namelen);/* XXX */ error = accept(td, &bsd_args); bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.name); - if (error) + if (error) { + if (error == EFAULT && linux_args.namelen != sizeof(struct sockaddr_in)) + return (EINVAL); return (error); + } if (linux_args.addr) { error = linux_sa_put(PTRIN(linux_args.addr)); if (error) { @@ -1135,7 +1140,7 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args) break; } if (name == -1) - return (EINVAL); + return (ENOPROTOOPT); bsd_args.name = name; bsd_args.val = PTRIN(linux_args.optval); |