patch-2.2.4 linux/arch/sparc64/kernel/sys_sparc32.c
Next file: linux/arch/sparc64/kernel/systbls.S
Previous file: linux/arch/sparc64/kernel/sys_sparc.c
Back to the patch index
Back to the overall index
- Lines: 722
- Date:
Wed Mar 10 16:53:37 1999
- Orig file:
v2.2.3/linux/arch/sparc64/kernel/sys_sparc32.c
- Orig date:
Thu Nov 19 09:56:27 1998
diff -u --recursive --new-file v2.2.3/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.100 1998/11/08 11:14:00 davem Exp $
+/* $Id: sys_sparc32.c,v 1.107 1999/03/05 13:21:02 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -43,6 +43,7 @@
#include <linux/poll.h>
#include <linux/personality.h>
#include <linux/stat.h>
+#include <linux/timex.h>
#include <asm/types.h>
#include <asm/ipc.h>
@@ -50,6 +51,8 @@
#include <asm/fpumacro.h>
#include <asm/semaphore.h>
+#include <net/scm.h>
+
/* Use this to get at 32-bit user passed pointers. */
/* Things to consider: the low-level assembly stub does
srl x, 0, x for first four arguments, so if you have
@@ -74,15 +77,6 @@
__ret; \
})
-static inline char * get_page(void)
-{
- char * res;
- res = (char *)__get_free_page(GFP_KERNEL);
- return res;
-}
-
-#define putname32 putname
-
/* In order to reduce some races, while at the same time doing additional
* checking and hopefully speeding things up, we copy filenames to the
* kernel data space before using them..
@@ -109,13 +103,13 @@
char *tmp, *result;
result = ERR_PTR(-ENOMEM);
- tmp = get_page();
+ tmp = (char *)__get_free_page(GFP_KERNEL);
if (tmp) {
int retval = do_getname32(filename, tmp);
result = tmp;
if (retval < 0) {
- putname32(tmp);
+ putname(tmp);
result = ERR_PTR(retval);
}
}
@@ -243,7 +237,10 @@
err = -EFAULT;
if (get_user (pad, (u32 *)uptr))
goto out;
- fourth.__pad = (void *)A(pad);
+ if(third == SETVAL)
+ fourth.val = (int)pad;
+ else
+ fourth.__pad = (void *)A(pad);
if (IPCOP_MASK (third) &
(IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |
IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
@@ -652,7 +649,7 @@
set_fs (KERNEL_DS);
err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
set_fs (old_fs);
- putname32 (spec);
+ putname (spec);
if (cmds == Q_GETQUOTA) {
__kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
((struct dqblk32 *)&d)->dqb_itime = i;
@@ -696,7 +693,7 @@
set_fs (KERNEL_DS);
ret = sys_statfs((const char *)pth, &s);
set_fs (old_fs);
- putname32 (pth);
+ putname (pth);
if (put_statfs(buf, &s))
return -EFAULT;
}
@@ -744,7 +741,7 @@
set_fs (KERNEL_DS);
ret = sys_utime(filenam, &t);
set_fs (old_fs);
- putname32 (filenam);
+ putname (filenam);
}
return ret;
}
@@ -796,8 +793,9 @@
}
inode = file->f_dentry->d_inode;
- retval = locks_verify_area((type == VERIFY_READ) ?
- FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
+ /* VERIFY_WRITE actually means a read, as we write to user space */
+ retval = locks_verify_area((type == VERIFY_WRITE
+ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
inode, file, file->f_pos, tot_len);
if (retval) {
if (iov != iovstack)
@@ -1106,13 +1104,17 @@
__put_user(*fdset, ufdset);
}
+#define MAX_SELECT_SECONDS \
+ ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
+
asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x)
{
- fd_set_buffer *fds;
+ fd_set_bits fds;
struct timeval32 *tvp = (struct timeval32 *)AA(tvp_x);
+ char *bits;
unsigned long nn;
long timeout;
- int ret;
+ int ret, size;
timeout = MAX_SCHEDULE_TIMEOUT;
if (tvp) {
@@ -1123,30 +1125,47 @@
|| (ret = __get_user(usec, &tvp->tv_usec)))
goto out_nofds;
- timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
- timeout += sec * HZ;
+ ret = -EINVAL;
+ if(sec < 0 || usec < 0)
+ goto out_nofds;
+
+ if ((unsigned long) sec < MAX_SELECT_SECONDS) {
+ timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
+ timeout += sec * (unsigned long) HZ;
+ }
}
+ ret = -EINVAL;
+ if (n < 0 || n > KFDS_NR)
+ goto out_nofds;
+
+ /*
+ * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
+ * since we used fdset we need to allocate memory in units of
+ * long-words.
+ */
ret = -ENOMEM;
- fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL);
- if (!fds)
+ size = FDS_BYTES(n);
+ bits = kmalloc(6 * size, GFP_KERNEL);
+ if (!bits)
goto out_nofds;
- ret = -EINVAL;
- if (n < 0)
- goto out;
- if (n > KFDS_NR)
- n = KFDS_NR;
+ fds.in = (unsigned long *) bits;
+ fds.out = (unsigned long *) (bits + size);
+ fds.ex = (unsigned long *) (bits + 2*size);
+ fds.res_in = (unsigned long *) (bits + 3*size);
+ fds.res_out = (unsigned long *) (bits + 4*size);
+ fds.res_ex = (unsigned long *) (bits + 5*size);
nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
- if ((ret = get_fd_set32(nn, fds->in, inp)) ||
- (ret = get_fd_set32(nn, fds->out, outp)) ||
- (ret = get_fd_set32(nn, fds->ex, exp)))
+ if ((ret = get_fd_set32(nn, fds.in, inp)) ||
+ (ret = get_fd_set32(nn, fds.out, outp)) ||
+ (ret = get_fd_set32(nn, fds.ex, exp)))
goto out;
- zero_fd_set(n, fds->res_in);
- zero_fd_set(n, fds->res_out);
- zero_fd_set(n, fds->res_ex);
+ zero_fd_set(n, fds.res_in);
+ zero_fd_set(n, fds.res_out);
+ zero_fd_set(n, fds.res_ex);
- ret = do_select(n, fds, &timeout);
+ ret = do_select(n, &fds, &timeout);
if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
time_t sec = 0, usec = 0;
@@ -1168,12 +1187,12 @@
ret = 0;
}
- set_fd_set32(nn, inp, fds->res_in);
- set_fd_set32(nn, outp, fds->res_out);
- set_fd_set32(nn, exp, fds->res_ex);
+ set_fd_set32(nn, inp, fds.res_in);
+ set_fd_set32(nn, outp, fds.res_out);
+ set_fd_set32(nn, exp, fds.res_ex);
out:
- free_page ((unsigned long)fds);
+ kfree(bits);
out_nofds:
return ret;
}
@@ -1213,7 +1232,7 @@
set_fs (KERNEL_DS);
ret = sys_newstat(filenam, &s);
set_fs (old_fs);
- putname32 (filenam);
+ putname (filenam);
if (putstat (statbuf, &s))
return -EFAULT;
}
@@ -1235,7 +1254,7 @@
set_fs (KERNEL_DS);
ret = sys_newlstat(filenam, &s);
set_fs (old_fs);
- putname32 (filenam);
+ putname (filenam);
if (putstat (statbuf, &s))
return -EFAULT;
}
@@ -2010,74 +2029,6 @@
return ret;
}
-struct timex32 {
- unsigned int modes;
- s32 offset;
- s32 freq;
- s32 maxerror;
- s32 esterror;
- int status;
- s32 constant;
- s32 precision;
- s32 tolerance;
- struct timeval32 time;
- s32 tick;
- s32 ppsfreq;
- s32 jitter;
- int shift;
- s32 stabil;
- s32 jitcnt;
- s32 calcnt;
- s32 errcnt;
- s32 stbcnt;
- int :32; int :32; int :32; int :32;
- int :32; int :32; int :32; int :32;
- int :32; int :32; int :32; int :32;
-};
-
-extern int do_adjtimex(struct timex *);
-
-asmlinkage int sys32_adjtimex(struct timex32 *txc_p)
-{
- struct timex t;
- int ret;
-
- ret = get_user (t.modes, &txc_p->modes);
- ret |= __get_user (t.offset, &txc_p->offset);
- ret |= __get_user (t.freq, &txc_p->freq);
- ret |= __get_user (t.maxerror, &txc_p->maxerror);
- ret |= __get_user (t.esterror, &txc_p->esterror);
- ret |= __get_user (t.status, &txc_p->status);
- ret |= __get_user (t.constant, &txc_p->constant);
- ret |= __get_user (t.tick, &txc_p->tick);
- ret |= __get_user (t.shift, &txc_p->shift);
- if (ret || (ret = do_adjtimex(&t)))
- return ret;
- ret = __put_user (t.modes, &txc_p->modes);
- ret |= __put_user (t.offset, &txc_p->offset);
- ret |= __put_user (t.freq, &txc_p->freq);
- ret |= __put_user (t.maxerror, &txc_p->maxerror);
- ret |= __put_user (t.esterror, &txc_p->esterror);
- ret |= __put_user (t.status, &txc_p->status);
- ret |= __put_user (t.constant, &txc_p->constant);
- ret |= __put_user (t.precision, &txc_p->precision);
- ret |= __put_user (t.tolerance, &txc_p->tolerance);
- ret |= __put_user (t.time.tv_sec, &txc_p->time.tv_sec);
- ret |= __put_user (t.time.tv_usec, &txc_p->time.tv_usec);
- ret |= __put_user (t.tick, &txc_p->tick);
- ret |= __put_user (t.ppsfreq, &txc_p->ppsfreq);
- ret |= __put_user (t.jitter, &txc_p->jitter);
- ret |= __put_user (t.shift, &txc_p->shift);
- ret |= __put_user (t.stabil, &txc_p->stabil);
- ret |= __put_user (t.jitcnt, &txc_p->jitcnt);
- ret |= __put_user (t.calcnt, &txc_p->calcnt);
- ret |= __put_user (t.errcnt, &txc_p->errcnt);
- ret |= __put_user (t.stbcnt, &txc_p->stbcnt);
- if (!ret)
- ret = time_state;
- return ret;
-}
-
/* XXX This really belongs in some header file... -DaveM */
#define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
16 for IP, 16 for IPX,
@@ -2131,9 +2082,44 @@
__kernel_size_t32 cmsg_len;
int cmsg_level;
int cmsg_type;
- unsigned char cmsg_data[0];
};
+/* Bleech... */
+#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
+#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
+
+#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
+
+#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
+#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
+#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
+
+#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
+ (struct cmsghdr32 *)(ctl) : \
+ (struct cmsghdr32 *)NULL)
+#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+
+__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
+ struct cmsghdr32 *__cmsg, int __cmsg_len)
+{
+ struct cmsghdr32 * __ptr;
+
+ __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
+ CMSG32_ALIGN(__cmsg_len));
+ if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
+ return NULL;
+
+ return __ptr;
+}
+
+__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
+ struct cmsghdr32 *__cmsg,
+ int __cmsg_len)
+{
+ return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
+ __cmsg, __cmsg_len);
+}
+
static inline int iov_from_user32_to_kern(struct iovec *kiov,
struct iovec32 *uiov32,
int niov)
@@ -2175,6 +2161,7 @@
kmsg->msg_control = (void *)A(tmp3);
err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
+ err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
@@ -2217,6 +2204,165 @@
return tot_len;
}
+/* There is a lot of hair here because the alignment rules (and
+ * thus placement) of cmsg headers and length are different for
+ * 32-bit apps. -DaveM
+ */
+static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
+ unsigned char *stackbuf, int stackbuf_size)
+{
+ struct cmsghdr32 *ucmsg;
+ struct cmsghdr *kcmsg, *kcmsg_base;
+ __kernel_size_t32 ucmlen;
+ __kernel_size_t kcmlen, tmp;
+
+ kcmlen = 0;
+ kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+ ucmsg = CMSG32_FIRSTHDR(kmsg);
+ while(ucmsg != NULL) {
+ if(get_user(ucmlen, &ucmsg->cmsg_len))
+ return -EFAULT;
+
+ /* Catch bogons. */
+ if(CMSG32_ALIGN(ucmlen) <
+ CMSG32_ALIGN(sizeof(struct cmsghdr32)))
+ return -EINVAL;
+ if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
+ + ucmlen) > kmsg->msg_controllen)
+ return -EINVAL;
+
+ tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+ CMSG_ALIGN(sizeof(struct cmsghdr)));
+ kcmlen += tmp;
+ ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+ }
+ if(kcmlen == 0)
+ return -EINVAL;
+
+ /* The kcmlen holds the 64-bit version of the control length.
+ * It may not be modified as we do not stick it into the kmsg
+ * until we have successfully copied over all of the data
+ * from the user.
+ */
+ if(kcmlen > stackbuf_size)
+ kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
+ if(kcmsg == NULL)
+ return -ENOBUFS;
+
+ /* Now copy them over neatly. */
+ memset(kcmsg, 0, kcmlen);
+ ucmsg = CMSG32_FIRSTHDR(kmsg);
+ while(ucmsg != NULL) {
+ __get_user(ucmlen, &ucmsg->cmsg_len);
+ tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+ CMSG_ALIGN(sizeof(struct cmsghdr)));
+ kcmsg->cmsg_len = tmp;
+ __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+ __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+
+ /* Copy over the data. */
+ if(copy_from_user(CMSG_DATA(kcmsg),
+ CMSG32_DATA(ucmsg),
+ (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
+ goto out_free_efault;
+
+ /* Advance. */
+ kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
+ ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+ }
+
+ /* Ok, looks like we made it. Hook it up and return success. */
+ kmsg->msg_control = kcmsg_base;
+ kmsg->msg_controllen = kcmlen;
+ return 0;
+
+out_free_efault:
+ if(kcmsg_base != (struct cmsghdr *)stackbuf)
+ kfree(kcmsg_base);
+ return -EFAULT;
+}
+
+static void put_cmsg32(struct msghdr *kmsg, int level, int type,
+ int len, void *data)
+{
+ struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
+ struct cmsghdr32 cmhdr;
+ int cmlen = CMSG32_LEN(len);
+
+ if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
+ kmsg->msg_flags |= MSG_CTRUNC;
+ return;
+ }
+
+ if(kmsg->msg_controllen < cmlen) {
+ kmsg->msg_flags |= MSG_CTRUNC;
+ cmlen = kmsg->msg_controllen;
+ }
+ cmhdr.cmsg_level = level;
+ cmhdr.cmsg_type = type;
+ cmhdr.cmsg_len = cmlen;
+
+ if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
+ return;
+ if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
+ return;
+ cmlen = CMSG32_SPACE(len);
+ kmsg->msg_control += cmlen;
+ kmsg->msg_controllen -= cmlen;
+}
+
+static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
+{
+ struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
+ int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
+ int fdnum = scm->fp->count;
+ struct file **fp = scm->fp->fp;
+ int *cmfptr;
+ int err = 0, i;
+
+ if (fdnum < fdmax)
+ fdmax = fdnum;
+
+ for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
+ int new_fd;
+ err = get_unused_fd();
+ if (err < 0)
+ break;
+ new_fd = err;
+ err = put_user(new_fd, cmfptr);
+ if (err) {
+ put_unused_fd(new_fd);
+ break;
+ }
+ /* Bump the usage count and install the file. */
+ fp[i]->f_count++;
+ current->files->fd[new_fd] = fp[i];
+ }
+
+ if (i > 0) {
+ int cmlen = CMSG32_LEN(i * sizeof(int));
+ if (!err)
+ err = put_user(SOL_SOCKET, &cm->cmsg_level);
+ if (!err)
+ err = put_user(SCM_RIGHTS, &cm->cmsg_type);
+ if (!err)
+ err = put_user(cmlen, &cm->cmsg_len);
+ if (!err) {
+ cmlen = CMSG32_SPACE(i * sizeof(int));
+ kmsg->msg_control += cmlen;
+ kmsg->msg_controllen -= cmlen;
+ }
+ }
+ if (i < fdnum)
+ kmsg->msg_flags |= MSG_CTRUNC;
+
+ /*
+ * All of the files that fit in the message have had their
+ * usage counts incremented, so we just free the list.
+ */
+ __scm_destroy(scm);
+}
+
asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
{
struct socket *sock;
@@ -2237,25 +2383,10 @@
total_len = err;
if(kern_msg.msg_controllen) {
- struct cmsghdr32 *ucmsg = (struct cmsghdr32 *)kern_msg.msg_control;
- unsigned long *kcmsg;
- __kernel_size_t32 cmlen;
-
- if(kern_msg.msg_controllen > sizeof(ctl) &&
- kern_msg.msg_controllen <= 256) {
- err = -ENOBUFS;
- ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
- if(!ctl_buf)
- goto out_freeiov;
- }
- __get_user(cmlen, &ucmsg->cmsg_len);
- kcmsg = (unsigned long *) ctl_buf;
- *kcmsg++ = (unsigned long)cmlen;
- err = -EFAULT;
- if(copy_from_user(kcmsg, &ucmsg->cmsg_level,
- kern_msg.msg_controllen - sizeof(__kernel_size_t32)))
- goto out_freectl;
- kern_msg.msg_control = ctl_buf;
+ err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
+ if(err)
+ goto out_freeiov;
+ ctl_buf = kern_msg.msg_control;
}
kern_msg.msg_flags = user_flags;
@@ -2269,7 +2400,6 @@
}
unlock_kernel();
-out_freectl:
/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
if(ctl_buf != ctl)
kfree(ctl_buf);
@@ -2310,26 +2440,43 @@
lock_kernel();
sock = sockfd_lookup(fd, &err);
if (sock != NULL) {
+ struct scm_cookie scm;
+
if (sock->file->f_flags & O_NONBLOCK)
user_flags |= MSG_DONTWAIT;
- err = sock_recvmsg(sock, &kern_msg, total_len, user_flags);
- if(err >= 0)
+ memset(&scm, 0, sizeof(scm));
+ err = sock->ops->recvmsg(sock, &kern_msg, total_len,
+ user_flags, &scm);
+ if(err >= 0) {
len = err;
+ if(!kern_msg.msg_control) {
+ if(sock->passcred || scm.fp)
+ kern_msg.msg_flags |= MSG_CTRUNC;
+ if(scm.fp)
+ __scm_destroy(&scm);
+ } else {
+ /* Wheee... */
+ if(sock->passcred)
+ put_cmsg32(&kern_msg,
+ SOL_SOCKET, SCM_CREDENTIALS,
+ sizeof(scm.creds), &scm.creds);
+ if(scm.fp != NULL)
+ scm_detach_fds32(&kern_msg, &scm);
+ }
+ }
sockfd_put(sock);
}
unlock_kernel();
if(uaddr != NULL && err >= 0)
err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
- if(err >= 0) {
- err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
- if(!err) {
- /* XXX Convert cmsg back into userspace 32-bit format... */
- err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr,
- &user_msg->msg_controllen);
- }
+ if(cmsg_ptr != 0 && err >= 0) {
+ u32 ucmsg_ptr = ((u32)(unsigned long)kern_msg.msg_control);
+ err = __put_user(ucmsg_ptr, &user_msg->msg_control);
+ err |= __put_user(kern_msg.msg_controllen, &user_msg->msg_controllen);
}
-
+ if(err >= 0)
+ err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
if(kern_msg.msg_iov != iov)
kfree(kern_msg.msg_iov);
out:
@@ -2653,7 +2800,7 @@
error = do_execve32(filename,
(u32 *)AA((u32)regs->u_regs[base + UREG_I1]),
(u32 *)AA((u32)regs->u_regs[base + UREG_I2]), regs);
- putname32(filename);
+ putname(filename);
if(!error) {
fprs_write(0);
@@ -2943,8 +3090,10 @@
info.addr = (unsigned long)mod;
info.size = mod->size;
info.flags = mod->flags;
- info.usecount = (mod_member_present(mod, can_unload)
- && mod->can_unload ? -1 : mod->usecount);
+ info.usecount =
+ ((mod_member_present(mod, can_unload)
+ && mod->can_unload)
+ ? -1 : atomic_read(&mod->uc.usecount));
if (copy_to_user(buf, &info, sizeof(struct module_info32)))
return -EFAULT;
@@ -3452,7 +3601,7 @@
ret = sys_utimes(kfilename, &ktvs[0]);
set_fs(old_fs);
- putname32(kfilename);
+ putname(kfilename);
}
return ret;
}
@@ -3575,5 +3724,78 @@
if (!ret && offset && put_user(of, offset))
return -EFAULT;
+ return ret;
+}
+
+/* Handle adjtimex compatability. */
+
+struct timex32 {
+ u32 modes;
+ s32 offset, freq, maxerror, esterror;
+ s32 status, constant, precision, tolerance;
+ struct timeval32 time;
+ s32 tick;
+ s32 ppsfreq, jitter, shift, stabil;
+ s32 jitcnt, calcnt, errcnt, stbcnt;
+ s32 :32; s32 :32; s32 :32; s32 :32;
+ s32 :32; s32 :32; s32 :32; s32 :32;
+ s32 :32; s32 :32; s32 :32; s32 :32;
+};
+
+extern int do_adjtimex(struct timex *);
+
+asmlinkage int sys32_adjtimex(struct timex32 *utp)
+{
+ struct timex txc;
+ int ret;
+
+ memset(&txc, 0, sizeof(struct timex));
+
+ if(get_user(txc.modes, &utp->modes) ||
+ __get_user(txc.offset, &utp->offset) ||
+ __get_user(txc.freq, &utp->freq) ||
+ __get_user(txc.maxerror, &utp->maxerror) ||
+ __get_user(txc.esterror, &utp->esterror) ||
+ __get_user(txc.status, &utp->status) ||
+ __get_user(txc.constant, &utp->constant) ||
+ __get_user(txc.precision, &utp->precision) ||
+ __get_user(txc.tolerance, &utp->tolerance) ||
+ __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+ __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+ __get_user(txc.tick, &utp->tick) ||
+ __get_user(txc.ppsfreq, &utp->ppsfreq) ||
+ __get_user(txc.jitter, &utp->jitter) ||
+ __get_user(txc.shift, &utp->shift) ||
+ __get_user(txc.stabil, &utp->stabil) ||
+ __get_user(txc.jitcnt, &utp->jitcnt) ||
+ __get_user(txc.calcnt, &utp->calcnt) ||
+ __get_user(txc.errcnt, &utp->errcnt) ||
+ __get_user(txc.stbcnt, &utp->stbcnt))
+ return -EFAULT;
+
+ ret = do_adjtimex(&txc);
+
+ if(put_user(txc.modes, &utp->modes) ||
+ __put_user(txc.offset, &utp->offset) ||
+ __put_user(txc.freq, &utp->freq) ||
+ __put_user(txc.maxerror, &utp->maxerror) ||
+ __put_user(txc.esterror, &utp->esterror) ||
+ __put_user(txc.status, &utp->status) ||
+ __put_user(txc.constant, &utp->constant) ||
+ __put_user(txc.precision, &utp->precision) ||
+ __put_user(txc.tolerance, &utp->tolerance) ||
+ __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+ __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+ __put_user(txc.tick, &utp->tick) ||
+ __put_user(txc.ppsfreq, &utp->ppsfreq) ||
+ __put_user(txc.jitter, &utp->jitter) ||
+ __put_user(txc.shift, &utp->shift) ||
+ __put_user(txc.stabil, &utp->stabil) ||
+ __put_user(txc.jitcnt, &utp->jitcnt) ||
+ __put_user(txc.calcnt, &utp->calcnt) ||
+ __put_user(txc.errcnt, &utp->errcnt) ||
+ __put_user(txc.stbcnt, &utp->stbcnt))
+ ret = -EFAULT;
+
return ret;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)