[PATCH] uml: preserve errno in error paths
The poster child for this patch is the third tuntap_user hunk. When an ioctl fails, it properly closes the opened file descriptor and returns. However, the close resets errno to 0, and the 'return errno' that follows returns 0 rather than the value that ioctl set. This caused the caller to believe that the device open succeeded and had opened file descriptor 0, which caused no end of interesting behavior. The rest of this patch is a pass through the UML sources looking for places where errno could be reset before being passed back out. A common culprit is printk, which could call write, being called before errno is returned. In some cases, where the code ends up being much smaller, I just deleted the printk. There was another case where a caller of run_helper looked at errno after a failure, rather than the return value of run_helper, which was the errno value that it wanted. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
64b7673f91
commit
b4fd310e16
|
@ -54,7 +54,7 @@ static int mcast_open(void *data)
|
|||
struct mcast_data *pri = data;
|
||||
struct sockaddr_in *sin = pri->mcast_addr;
|
||||
struct ip_mreq mreq;
|
||||
int fd = -EINVAL, yes = 1, err = -EINVAL;;
|
||||
int fd, yes = 1, err = 0;
|
||||
|
||||
|
||||
if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
|
||||
|
@ -65,13 +65,14 @@ static int mcast_open(void *data)
|
|||
if (fd < 0){
|
||||
printk("mcast_open : data socket failed, errno = %d\n",
|
||||
errno);
|
||||
fd = -errno;
|
||||
err = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
|
||||
printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
|
||||
errno);
|
||||
err = -errno;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
|
@ -80,6 +81,7 @@ static int mcast_open(void *data)
|
|||
sizeof(pri->ttl)) < 0) {
|
||||
printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
|
||||
errno);
|
||||
err = -errno;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
|
@ -87,12 +89,14 @@ static int mcast_open(void *data)
|
|||
if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
|
||||
printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
|
||||
errno);
|
||||
err = -errno;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
/* bind socket to mcast address */
|
||||
if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
|
||||
printk("mcast_open : data bind failed, errno = %d\n", errno);
|
||||
err = -errno;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
|
@ -107,14 +111,15 @@ static int mcast_open(void *data)
|
|||
"interface on the host.\n");
|
||||
printk("eth0 should be configured in order to use the "
|
||||
"multicast transport.\n");
|
||||
err = -errno;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
out:
|
||||
return fd;
|
||||
|
||||
out_close:
|
||||
os_close_file(fd);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -173,9 +173,9 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
|
|||
if(notify_sock < 0){
|
||||
notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0);
|
||||
if(notify_sock < 0){
|
||||
printk("mconsole_notify - socket failed, errno = %d\n",
|
||||
errno);
|
||||
err = -errno;
|
||||
printk("mconsole_notify - socket failed, errno = %d\n",
|
||||
err);
|
||||
}
|
||||
}
|
||||
unlock_notify();
|
||||
|
@ -198,8 +198,8 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
|
|||
n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target,
|
||||
sizeof(target));
|
||||
if(n < 0){
|
||||
printk("mconsole_notify - sendto failed, errno = %d\n", errno);
|
||||
err = -errno;
|
||||
printk("mconsole_notify - sendto failed, errno = %d\n", errno);
|
||||
}
|
||||
return(err);
|
||||
}
|
||||
|
|
|
@ -43,8 +43,9 @@ static int pts_open(int input, int output, int primary, void *d,
|
|||
|
||||
fd = get_pty();
|
||||
if(fd < 0){
|
||||
err = -errno;
|
||||
printk("open_pts : Failed to open pts\n");
|
||||
return(-errno);
|
||||
return err;
|
||||
}
|
||||
if(data->raw){
|
||||
CATCH_EINTR(err = tcgetattr(fd, &data->tt));
|
||||
|
|
|
@ -110,13 +110,15 @@ int xterm_open(int input, int output, int primary, void *d,
|
|||
|
||||
fd = mkstemp(file);
|
||||
if(fd < 0){
|
||||
err = -errno;
|
||||
printk("xterm_open : mkstemp failed, errno = %d\n", errno);
|
||||
return(-errno);
|
||||
return err;
|
||||
}
|
||||
|
||||
if(unlink(file)){
|
||||
err = -errno;
|
||||
printk("xterm_open : unlink failed, errno = %d\n", errno);
|
||||
return(-errno);
|
||||
return err;
|
||||
}
|
||||
os_close_file(fd);
|
||||
|
||||
|
|
|
@ -85,8 +85,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
|
|||
data.fd = fds[1];
|
||||
pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
|
||||
if(pid < 0){
|
||||
printk("run_helper : clone failed, errno = %d\n", errno);
|
||||
ret = -errno;
|
||||
printk("run_helper : clone failed, errno = %d\n", errno);
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
|
|||
unsigned long *stack_out, int stack_order)
|
||||
{
|
||||
unsigned long stack, sp;
|
||||
int pid, status;
|
||||
int pid, status, err;
|
||||
|
||||
stack = alloc_stack(stack_order, um_in_interrupt());
|
||||
if(stack == 0) return(-ENOMEM);
|
||||
|
@ -130,16 +130,18 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
|
|||
sp = stack + (page_size() << stack_order) - sizeof(void *);
|
||||
pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
|
||||
if(pid < 0){
|
||||
err = -errno;
|
||||
printk("run_helper_thread : clone failed, errno = %d\n",
|
||||
errno);
|
||||
return(-errno);
|
||||
return err;
|
||||
}
|
||||
if(stack_out == NULL){
|
||||
CATCH_EINTR(pid = waitpid(pid, &status, 0));
|
||||
if(pid < 0){
|
||||
err = -errno;
|
||||
printk("run_helper_thread - wait failed, errno = %d\n",
|
||||
errno);
|
||||
pid = -errno;
|
||||
pid = err;
|
||||
}
|
||||
if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
|
||||
printk("run_helper_thread - thread returned status "
|
||||
|
@ -156,8 +158,8 @@ int helper_wait(int pid)
|
|||
|
||||
CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG));
|
||||
if(ret < 0){
|
||||
ret = -errno;
|
||||
printk("helper_wait : waitpid failed, errno = %d\n", errno);
|
||||
return(-errno);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
|
|
@ -109,18 +109,14 @@ int raw(int fd)
|
|||
int err;
|
||||
|
||||
CATCH_EINTR(err = tcgetattr(fd, &tt));
|
||||
if (err < 0) {
|
||||
printk("tcgetattr failed, errno = %d\n", errno);
|
||||
return(-errno);
|
||||
}
|
||||
if(err < 0)
|
||||
return -errno;
|
||||
|
||||
cfmakeraw(&tt);
|
||||
|
||||
CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
|
||||
if (err < 0) {
|
||||
printk("tcsetattr failed, errno = %d\n", errno);
|
||||
return(-errno);
|
||||
}
|
||||
if(err < 0)
|
||||
return -errno;
|
||||
|
||||
/* XXX tcsetattr could have applied only some changes
|
||||
* (and cfmakeraw() is a set of changes) */
|
||||
|
|
|
@ -313,15 +313,16 @@ static int init_aio_26(void)
|
|||
int err;
|
||||
|
||||
if(io_setup(256, &ctx)){
|
||||
err = -errno;
|
||||
printk("aio_thread failed to initialize context, err = %d\n",
|
||||
errno);
|
||||
return -errno;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = run_helper_thread(aio_thread, NULL,
|
||||
CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
|
||||
if(err < 0)
|
||||
return -errno;
|
||||
return err;
|
||||
|
||||
aio_pid = err;
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
|
|||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct iovec iov;
|
||||
int pid, n;
|
||||
int pid, n, err;
|
||||
|
||||
sprintf(version_buf, "%d", UML_NET_VERSION);
|
||||
|
||||
|
@ -105,9 +105,10 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
|
|||
n = recvmsg(me, &msg, 0);
|
||||
*used_out = n;
|
||||
if(n < 0){
|
||||
err = -errno;
|
||||
printk("tuntap_open_tramp : recvmsg failed - errno = %d\n",
|
||||
errno);
|
||||
return(-errno);
|
||||
return err;
|
||||
}
|
||||
CATCH_EINTR(waitpid(pid, NULL, 0));
|
||||
|
||||
|
@ -147,9 +148,10 @@ static int tuntap_open(void *data)
|
|||
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
||||
strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
|
||||
if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
|
||||
err = -errno;
|
||||
printk("TUNSETIFF failed, errno = %d\n", errno);
|
||||
os_close_file(pri->fd);
|
||||
return(-errno);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -119,15 +119,11 @@ int os_window_size(int fd, int *rows, int *cols)
|
|||
|
||||
int os_new_tty_pgrp(int fd, int pid)
|
||||
{
|
||||
if(ioctl(fd, TIOCSCTTY, 0) < 0){
|
||||
printk("TIOCSCTTY failed, errno = %d\n", errno);
|
||||
return(-errno);
|
||||
}
|
||||
if(ioctl(fd, TIOCSCTTY, 0) < 0)
|
||||
return -errno;
|
||||
|
||||
if(tcsetpgrp(fd, pid) < 0){
|
||||
printk("tcsetpgrp failed, errno = %d\n", errno);
|
||||
return(-errno);
|
||||
}
|
||||
if(tcsetpgrp(fd, pid) < 0)
|
||||
return -errno;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -146,18 +142,12 @@ int os_set_slip(int fd)
|
|||
int disc, sencap;
|
||||
|
||||
disc = N_SLIP;
|
||||
if(ioctl(fd, TIOCSETD, &disc) < 0){
|
||||
printk("Failed to set slip line discipline - "
|
||||
"errno = %d\n", errno);
|
||||
return(-errno);
|
||||
}
|
||||
if(ioctl(fd, TIOCSETD, &disc) < 0)
|
||||
return -errno;
|
||||
|
||||
sencap = 0;
|
||||
if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){
|
||||
printk("Failed to set slip encapsulation - "
|
||||
"errno = %d\n", errno);
|
||||
return(-errno);
|
||||
}
|
||||
if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
|
||||
return -errno;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -180,22 +170,15 @@ int os_sigio_async(int master, int slave)
|
|||
int flags;
|
||||
|
||||
flags = fcntl(master, F_GETFL);
|
||||
if(flags < 0) {
|
||||
printk("fcntl F_GETFL failed, errno = %d\n", errno);
|
||||
return(-errno);
|
||||
}
|
||||
if(flags < 0)
|
||||
return errno;
|
||||
|
||||
if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
|
||||
(fcntl(master, F_SETOWN, os_getpid()) < 0)){
|
||||
printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n",
|
||||
errno);
|
||||
return(-errno);
|
||||
}
|
||||
(fcntl(master, F_SETOWN, os_getpid()) < 0))
|
||||
return -errno;
|
||||
|
||||
if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){
|
||||
printk("fcntl F_SETFL failed, errno = %d\n", errno);
|
||||
return(-errno);
|
||||
}
|
||||
if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
|
||||
return -errno;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -255,7 +238,7 @@ int os_file_mode(char *file, struct openflags *mode_out)
|
|||
|
||||
int os_open_file(char *file, struct openflags flags, int mode)
|
||||
{
|
||||
int fd, f = 0;
|
||||
int fd, err, f = 0;
|
||||
|
||||
if(flags.r && flags.w) f = O_RDWR;
|
||||
else if(flags.r) f = O_RDONLY;
|
||||
|
@ -272,8 +255,9 @@ int os_open_file(char *file, struct openflags flags, int mode)
|
|||
return(-errno);
|
||||
|
||||
if(flags.cl && fcntl(fd, F_SETFD, 1)){
|
||||
err = -errno;
|
||||
os_close_file(fd);
|
||||
return(-errno);
|
||||
return err;
|
||||
}
|
||||
|
||||
return(fd);
|
||||
|
@ -383,9 +367,9 @@ int os_file_size(char *file, unsigned long long *size_out)
|
|||
return(fd);
|
||||
}
|
||||
if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
|
||||
err = -errno;
|
||||
printk("Couldn't get the block size of \"%s\", "
|
||||
"errno = %d\n", file, errno);
|
||||
err = -errno;
|
||||
os_close_file(fd);
|
||||
return(err);
|
||||
}
|
||||
|
@ -473,11 +457,14 @@ int os_pipe(int *fds, int stream, int close_on_exec)
|
|||
|
||||
int os_set_fd_async(int fd, int owner)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* XXX This should do F_GETFL first */
|
||||
if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
|
||||
err = -errno;
|
||||
printk("os_set_fd_async : failed to set O_ASYNC and "
|
||||
"O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
|
||||
return(-errno);
|
||||
return err;
|
||||
}
|
||||
#ifdef notdef
|
||||
if(fcntl(fd, F_SETFD, 1) < 0){
|
||||
|
@ -488,10 +475,11 @@ int os_set_fd_async(int fd, int owner)
|
|||
|
||||
if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
|
||||
(fcntl(fd, F_SETOWN, owner) < 0)){
|
||||
err = -errno;
|
||||
printk("os_set_fd_async : Failed to fcntl F_SETOWN "
|
||||
"(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
|
||||
owner, errno);
|
||||
return(-errno);
|
||||
return err;
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
@ -516,11 +504,9 @@ int os_set_fd_block(int fd, int blocking)
|
|||
if(blocking) flags &= ~O_NONBLOCK;
|
||||
else flags |= O_NONBLOCK;
|
||||
|
||||
if(fcntl(fd, F_SETFL, flags) < 0){
|
||||
printk("Failed to change blocking on fd # %d, errno = %d\n",
|
||||
fd, errno);
|
||||
return(-errno);
|
||||
}
|
||||
if(fcntl(fd, F_SETFL, flags) < 0)
|
||||
return -errno;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -609,11 +595,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec)
|
|||
int sock, err;
|
||||
|
||||
sock = socket(PF_UNIX, SOCK_DGRAM, 0);
|
||||
if (sock < 0){
|
||||
printk("create_unix_socket - socket failed, errno = %d\n",
|
||||
errno);
|
||||
return(-errno);
|
||||
}
|
||||
if(sock < 0)
|
||||
return -errno;
|
||||
|
||||
if(close_on_exec) {
|
||||
err = os_set_exec_close(sock, 1);
|
||||
|
@ -628,11 +611,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec)
|
|||
snprintf(addr.sun_path, len, "%s", file);
|
||||
|
||||
err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
|
||||
if (err < 0){
|
||||
printk("create_listening_socket at '%s' - bind failed, "
|
||||
"errno = %d\n", file, errno);
|
||||
return(-errno);
|
||||
}
|
||||
if(err < 0)
|
||||
return -errno;
|
||||
|
||||
return(sock);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue