Here is a refresh of the EFAULT patch. This fixes a lot of crashes in
LTP, and presumably in regular applications too. This still needs to
have the checking foldded into lock_user(), but there were a handful
of small fixes since this patch was last sent out.
Stuart
Stuart R. Anderson [EMAIL PROTECTED]
Network & Software Engineering http://www.netsweng.com/
1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F
BD03 0A62 E534 37A7 9149
Index: qemu/exec.c
===================================================================
--- qemu.orig/exec.c 2007-03-26 11:18:49.000000000 -0400
+++ qemu/exec.c 2007-03-26 11:20:06.000000000 -0400
@@ -1785,6 +1785,29 @@
spin_unlock(&tb_lock);
}
+int page_check_range(target_ulong start, target_ulong len, int flags)
+{
+ PageDesc *p;
+ target_ulong end;
+ target_ulong addr;
+
+ end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
+ start = start & TARGET_PAGE_MASK;
+
+ if( end < start ) return EFAULT; /* we've wrapped around */
+ for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
+ p = page_find(addr >> TARGET_PAGE_BITS);
+ if( !p ) return EFAULT;
+ if( !(p->flags & PAGE_VALID) ) return EFAULT;
+
+ if (!(p->flags & PAGE_READ) &&
+ (flags & PAGE_READ) ) return EFAULT;
+ if (!(p->flags & PAGE_WRITE) &&
+ (flags & PAGE_WRITE) ) return EFAULT;
+ }
+ return 0;
+}
+
/* called from signal handler: invalidate the code and unprotect the
page. Return TRUE if the fault was succesfully handled. */
int page_unprotect(target_ulong address, unsigned long pc, void *puc)
Index: qemu/cpu-all.h
===================================================================
--- qemu.orig/cpu-all.h 2007-03-26 11:18:49.000000000 -0400
+++ qemu/cpu-all.h 2007-03-26 11:20:06.000000000 -0400
@@ -689,6 +689,7 @@
int page_get_flags(target_ulong address);
void page_set_flags(target_ulong start, target_ulong end, int flags);
void page_unprotect_range(target_ulong data, target_ulong data_size);
+int page_check_range(target_ulong start, target_ulong len, int flags);
#define SINGLE_CPU_DEFINES
#ifdef SINGLE_CPU_DEFINES
Index: qemu/linux-user/syscall.c
===================================================================
--- qemu.orig/linux-user/syscall.c 2007-03-26 11:20:05.000000000 -0400
+++ qemu/linux-user/syscall.c 2007-03-26 14:11:21.000000000 -0400
@@ -406,28 +406,36 @@
return ret;
}
-static inline void target_to_host_sockaddr(struct sockaddr *addr,
+static inline long target_to_host_sockaddr(struct sockaddr *addr,
target_ulong target_addr,
- socklen_t len)
+ socklen_t len,
+ int pg_access)
{
+ long ret = 0;
struct target_sockaddr *target_saddr;
target_saddr = lock_user(target_addr, len, 1);
+ if( ret=page_check_range(target_saddr,len,pg_access) ) return ret;
memcpy(addr, target_saddr, len);
addr->sa_family = tswap16(target_saddr->sa_family);
unlock_user(target_saddr, target_addr, 0);
+ return ret;
}
-static inline void host_to_target_sockaddr(target_ulong target_addr,
+static inline long host_to_target_sockaddr(target_ulong target_addr,
struct sockaddr *addr,
- socklen_t len)
+ socklen_t len,
+ int pg_access)
{
+ long ret = 0;
struct target_sockaddr *target_saddr;
target_saddr = lock_user(target_addr, len, 0);
+ if( ret=page_check_range(target_saddr,len,pg_access) ) return ret;
memcpy(target_saddr, addr, len);
target_saddr->sa_family = tswap16(addr->sa_family);
unlock_user(target_saddr, target_addr, len);
+ return ret;
}
/* ??? Should this also swap msgh->name? */
@@ -788,18 +796,20 @@
static long do_bind(int sockfd, target_ulong target_addr,
socklen_t addrlen)
{
+ long ret = 0;
void *addr = alloca(addrlen);
- target_to_host_sockaddr(addr, target_addr, addrlen);
+ if( ret=target_to_host_sockaddr(addr, target_addr, addrlen,PAGE_READ) ) return -ret;
return get_errno(bind(sockfd, addr, addrlen));
}
static long do_connect(int sockfd, target_ulong target_addr,
socklen_t addrlen)
{
+ long ret = 0;
void *addr = alloca(addrlen);
- target_to_host_sockaddr(addr, target_addr, addrlen);
+ if( ret=target_to_host_sockaddr(addr, target_addr, addrlen,PAGE_READ) ) return -ret;
return get_errno(connect(sockfd, addr, addrlen));
}
@@ -814,11 +824,19 @@
target_ulong target_vec;
lock_user_struct(msgp, target_msg, 1);
+ if( send )
+ if( ret=page_check_range(msgp,sizeof(*msgp),PAGE_READ) ) return -ret;
+ else
+ if( ret=page_check_range(msgp,sizeof(*msgp),PAGE_WRITE) ) return -ret;
if (msgp->msg_name) {
msg.msg_namelen = tswap32(msgp->msg_namelen);
msg.msg_name = alloca(msg.msg_namelen);
- target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
- msg.msg_namelen);
+ if( send )
+ if( ret=target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
+ msg.msg_namelen,PAGE_READ) ) return -ret;
+ else
+ if( ret=target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
+ msg.msg_namelen,PAGE_WRITE) ) return -ret;
} else {
msg.msg_name = NULL;
msg.msg_namelen = 0;
@@ -851,11 +869,11 @@
{
socklen_t addrlen = tget32(target_addrlen);
void *addr = alloca(addrlen);
- long ret;
+ long ret,ret2;
ret = get_errno(accept(fd, addr, &addrlen));
if (!is_error(ret)) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
+ if( ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret2;
tput32(target_addrlen, addrlen);
}
return ret;
@@ -864,13 +882,17 @@
static long do_getpeername(int fd, target_ulong target_addr,
target_ulong target_addrlen)
{
- socklen_t addrlen = tget32(target_addrlen);
- void *addr = alloca(addrlen);
- long ret;
+ socklen_t addrlen;
+ void *addr;
+ long ret,ret2;
+
+ if( ret=page_check_range(target_addrlen,sizeof(socklen_t),PAGE_WRITE) ) return -ret;
+ addrlen = tget32(target_addrlen);
+ addr = alloca(addrlen);
ret = get_errno(getpeername(fd, addr, &addrlen));
if (!is_error(ret)) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
+ if( ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret2;
tput32(target_addrlen, addrlen);
}
return ret;
@@ -879,13 +901,17 @@
static long do_getsockname(int fd, target_ulong target_addr,
target_ulong target_addrlen)
{
- socklen_t addrlen = tget32(target_addrlen);
- void *addr = alloca(addrlen);
- long ret;
+ socklen_t addrlen;
+ void *addr;
+ long ret,ret2;
+
+ if( ret=page_check_range(target_addrlen,sizeof(socklen_t),PAGE_WRITE) ) return -ret;
+ addrlen = tget32(target_addrlen);
+ addr = alloca(addrlen);
ret = get_errno(getsockname(fd, addr, &addrlen));
if (!is_error(ret)) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
+ if( ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret2;
tput32(target_addrlen, addrlen);
}
return ret;
@@ -913,9 +939,10 @@
long ret;
host_msg = lock_user(msg, len, 1);
+ if( ret=page_check_range(host_msg,len,PAGE_READ) ) return -ret;
if (target_addr) {
addr = alloca(addrlen);
- target_to_host_sockaddr(addr, target_addr, addrlen);
+ if( ret=target_to_host_sockaddr(addr, target_addr, addrlen, PAGE_READ) ) return -ret;
ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
} else {
ret = get_errno(send(fd, host_msg, len, flags));
@@ -930,9 +957,10 @@
socklen_t addrlen;
void *addr;
void *host_msg;
- long ret;
+ long ret,ret2;
host_msg = lock_user(msg, len, 0);
+ if( ret2=page_check_range(host_msg,len,PAGE_WRITE) ) return -ret2;
if (target_addr) {
addrlen = tget32(target_addrlen);
addr = alloca(addrlen);
@@ -943,7 +971,7 @@
}
if (!is_error(ret)) {
if (target_addr) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
+ if( ret2=host_to_target_sockaddr(target_addr, addr, addrlen, PAGE_WRITE) ) return -ret2;
tput32(target_addrlen, addrlen);
}
unlock_user(host_msg, msg, len);
@@ -1150,13 +1178,16 @@
target_ulong __unused4;
};
-static inline void target_to_host_ipc_perm(struct ipc_perm *host_ip,
- target_ulong target_addr)
+static inline long target_to_host_ipc_perm(struct ipc_perm *host_ip,
+ target_ulong target_addr,
+ int pg_access)
{
+ long ret = 0;
struct target_ipc_perm *target_ip;
struct target_semid_ds *target_sd;
lock_user_struct(target_sd, target_addr, 1);
+ if( ret=page_check_range(target_sd,sizeof(*target_sd),pg_access) ) return -ret;
target_ip=&(target_sd->sem_perm);
host_ip->__key = tswapl(target_ip->__key);
host_ip->uid = tswapl(target_ip->uid);
@@ -1165,15 +1196,20 @@
host_ip->cgid = tswapl(target_ip->cgid);
host_ip->mode = tswapl(target_ip->mode);
unlock_user_struct(target_sd, target_addr, 0);
+
+ return ret;
}
-static inline void host_to_target_ipc_perm(target_ulong target_addr,
- struct ipc_perm *host_ip)
+static inline long host_to_target_ipc_perm(target_ulong target_addr,
+ struct ipc_perm *host_ip,
+ int pg_access)
{
+ long ret = 0;
struct target_ipc_perm *target_ip;
struct target_semid_ds *target_sd;
lock_user_struct(target_sd, target_addr, 0);
+ if( ret=page_check_range(target_sd,sizeof(*target_sd),pg_access) ) return -ret;
target_ip = &(target_sd->sem_perm);
target_ip->__key = tswapl(host_ip->__key);
target_ip->uid = tswapl(host_ip->uid);
@@ -1182,32 +1218,44 @@
target_ip->cgid = tswapl(host_ip->cgid);
target_ip->mode = tswapl(host_ip->mode);
unlock_user_struct(target_sd, target_addr, 1);
+
+ return ret;
}
-static inline void target_to_host_semid_ds(struct semid_ds *host_sd,
- target_ulong target_addr)
+static inline long target_to_host_semid_ds(struct semid_ds *host_sd,
+ target_ulong target_addr,
+ int pg_access)
{
+ long ret = 0;
struct target_semid_ds *target_sd;
lock_user_struct(target_sd, target_addr, 1);
- target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
+ if( ret=page_check_range(target_sd,sizeof(*target_sd),pg_access) ) return -ret;
+ target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr,pg_access);
host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
host_sd->sem_otime = tswapl(target_sd->sem_otime);
host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
unlock_user_struct(target_sd, target_addr, 0);
+
+ return ret;
}
-static inline void host_to_target_semid_ds(target_ulong target_addr,
- struct semid_ds *host_sd)
+static inline long host_to_target_semid_ds(target_ulong target_addr,
+ struct semid_ds *host_sd,
+ int pg_access)
{
+ long ret = 0;
struct target_semid_ds *target_sd;
lock_user_struct(target_sd, target_addr, 0);
- host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
+ host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm),pg_access);
+ if( ret=page_check_range(target_sd,sizeof(*target_sd),pg_access) ) return -ret;
target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
target_sd->sem_otime = tswapl(host_sd->sem_otime);
target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
unlock_user_struct(target_sd, target_addr, 1);
+
+ return ret;
}
union semun {
@@ -1222,11 +1270,13 @@
target_long array;
};
-static inline void target_to_host_semun(unsigned long cmd,
+static inline long target_to_host_semun(unsigned long cmd,
union semun *host_su,
target_ulong target_addr,
- struct semid_ds *ds)
+ struct semid_ds *ds,
+ int pg_access)
{
+ long ret = 0;
union target_semun *target_su;
switch( cmd ) {
@@ -1235,26 +1285,32 @@
case IPC_STAT:
case IPC_SET:
lock_user_struct(target_su, target_addr, 1);
- target_to_host_semid_ds(ds,target_su->buf);
+ if( ret=page_check_range(target_su,sizeof(*target_su),pg_access) ) return -ret;
+ if( ret=target_to_host_semid_ds(ds,target_su->buf, pg_access) ) return -ret;
host_su->buf = ds;
unlock_user_struct(target_su, target_addr, 0);
break;
case GETVAL:
case SETVAL:
lock_user_struct(target_su, target_addr, 1);
+ if( ret=page_check_range(target_su,sizeof(*target_su),pg_access) ) return -ret;
host_su->val = tswapl(target_su->val);
unlock_user_struct(target_su, target_addr, 0);
break;
default:
host_su->array = tswapl(target_su->array);
}
+
+ return ret;
}
-static inline void host_to_target_semun(unsigned long cmd,
+static inline long host_to_target_semun(unsigned long cmd,
target_ulong target_addr,
union semun *host_su,
- struct semid_ds *ds)
+ struct semid_ds *ds,
+ int pg_access)
{
+ long ret = 0;
union target_semun *target_su;
switch( cmd ) {
@@ -1263,18 +1319,22 @@
case IPC_STAT:
case IPC_SET:
lock_user_struct(target_su, target_addr, 0);
- host_to_target_semid_ds(target_su->buf,ds);
+ if( ret=page_check_range(target_su,sizeof(*target_su),pg_access) ) return -ret;
+ if( ret=host_to_target_semid_ds(target_su->buf,ds, pg_access) ) return -ret;
unlock_user_struct(target_su, target_addr, 1);
break;
case GETVAL:
case SETVAL:
lock_user_struct(target_su, target_addr, 0);
+ if( ret=page_check_range(target_su,sizeof(*target_su),pg_access) ) return -ret;
target_su->val = tswapl(host_su->val);
unlock_user_struct(target_su, target_addr, 1);
break;
default:
target_su->array = tswapl(host_su->array);
}
+
+ return ret;
}
static inline long do_semctl(long first, long second, long third, long ptr)
@@ -1286,34 +1346,34 @@
switch( cmd ) {
case GETVAL:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
+ if( ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_WRITE) ) return -ret;
ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
+ host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_WRITE);
break;
case SETVAL:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
+ if( ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_READ) ) return -ret;
ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
+ host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_READ);
break;
case GETALL:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
+ if( ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_WRITE) ) return -ret;
ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
+ host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_WRITE);
break;
case SETALL:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
+ if( ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_READ) ) return -ret;
ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
+ host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_READ);
break;
case IPC_STAT:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
+ if( ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_WRITE) ) return -ret;
ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
+ host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_READ);
break;
case IPC_SET:
- target_to_host_semun(cmd,&arg,ptr,&dsarg);
+ if( ret=target_to_host_semun(cmd,&arg,ptr,&dsarg,PAGE_READ) ) return -ret;
ret = get_errno(semctl(first, second, cmd, arg));
- host_to_target_semun(cmd,ptr,&arg,&dsarg);
+ host_to_target_semun(cmd,ptr,&arg,&dsarg,PAGE_READ);
break;
default:
ret = get_errno(semctl(first, second, cmd, arg));
@@ -1340,13 +1400,16 @@
target_ulong __unused5;
};
-static inline void target_to_host_msqid_ds(struct msqid_ds *host_md,
- target_ulong target_addr)
+static inline long target_to_host_msqid_ds(struct msqid_ds *host_md,
+ target_ulong target_addr,
+ int pg_access)
{
+ long ret = 0;
struct target_msqid_ds *target_md;
lock_user_struct(target_md, target_addr, 1);
- target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
+ if( ret=page_check_range(target_md,sizeof(*target_md),pg_access) ) return -ret;
+ target_to_host_ipc_perm(&(host_md->msg_perm),target_addr,pg_access);
host_md->msg_stime = tswapl(target_md->msg_stime);
host_md->msg_rtime = tswapl(target_md->msg_rtime);
host_md->msg_ctime = tswapl(target_md->msg_ctime);
@@ -1356,15 +1419,19 @@
host_md->msg_lspid = tswapl(target_md->msg_lspid);
host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
unlock_user_struct(target_md, target_addr, 0);
+ return ret;
}
-static inline void host_to_target_msqid_ds(target_ulong target_addr,
- struct msqid_ds *host_md)
+static inline long host_to_target_msqid_ds(target_ulong target_addr,
+ struct msqid_ds *host_md,
+ int pg_access)
{
+ long ret = 0;
struct target_msqid_ds *target_md;
lock_user_struct(target_md, target_addr, 0);
- host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
+ if( ret=page_check_range(target_md,sizeof(*target_md),pg_access) ) return -ret;
+ host_to_target_ipc_perm(target_addr,&(host_md->msg_perm),pg_access);
target_md->msg_stime = tswapl(host_md->msg_stime);
target_md->msg_rtime = tswapl(host_md->msg_rtime);
target_md->msg_ctime = tswapl(host_md->msg_ctime);
@@ -1374,6 +1441,8 @@
target_md->msg_lspid = tswapl(host_md->msg_lspid);
target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
unlock_user_struct(target_md, target_addr, 1);
+
+ return ret;
}
static inline long do_msgctl(long first, long second, long ptr)
@@ -1383,10 +1452,15 @@
long ret = 0;
switch( cmd ) {
case IPC_STAT:
+ if( ret=target_to_host_msqid_ds(&dsarg,ptr,PAGE_WRITE) ) return -ret;
+ ret = get_errno(msgctl(first, cmd, &dsarg));
+ host_to_target_msqid_ds(ptr,&dsarg,PAGE_WRITE);
+ break;
case IPC_SET:
- target_to_host_msqid_ds(&dsarg,ptr);
+ if( ret=target_to_host_msqid_ds(&dsarg,ptr,PAGE_READ) ) return -ret;
ret = get_errno(msgctl(first, cmd, &dsarg));
- host_to_target_msqid_ds(ptr,&dsarg);
+ host_to_target_msqid_ds(ptr,&dsarg,PAGE_WRITE);
+ break;
default:
ret = get_errno(msgctl(first, cmd, &dsarg));
}
@@ -1405,6 +1479,7 @@
long ret = 0;
lock_user_struct(target_mb,msgp,0);
+ if( ret=page_check_range(target_mb,sizeof(long)+msgsz,PAGE_READ) ) return -ret;
host_mb = malloc(msgsz+sizeof(long));
host_mb->mtype = tswapl(target_mb->mtype);
memcpy(host_mb->mtext,target_mb->mtext,msgsz);
@@ -1422,6 +1497,7 @@
long ret = 0;
lock_user_struct(target_mb,msgp,0);
+ if( ret=page_check_range(target_mb,sizeof(long)+msgsz,PAGE_WRITE) ) return -ret;
host_mb = malloc(msgsz+sizeof(long));
ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
if( ret > 0 )
@@ -2701,6 +2777,7 @@
struct target_sigaction act, oact, *pact;
if (arg2) {
lock_user_struct(old_act, arg2, 1);
+ if( ret=page_check_range(old_act,sizeof(*old_act),PAGE_READ) ) return -ret;
act._sa_handler = old_act->_sa_handler;
target_siginitset(&act.sa_mask, old_act->sa_mask);
act.sa_flags = old_act->sa_flags;
@@ -2713,6 +2790,7 @@
ret = get_errno(do_sigaction(arg1, pact, &oact));
if (!is_error(ret) && arg3) {
lock_user_struct(old_act, arg3, 0);
+ if( ret=page_check_range(old_act,sizeof(*old_act),PAGE_WRITE) ) return -ret;
old_act->_sa_handler = oact._sa_handler;
old_act->sa_mask = oact.sa_mask.sig[0];
old_act->sa_flags = oact.sa_flags;
@@ -2724,6 +2802,7 @@
if (arg2) {
lock_user_struct(old_act, arg2, 1);
+ if( ret=page_check_range(old_act,sizeof(*old_act),PAGE_READ) ) return -ret;
act._sa_handler = old_act->_sa_handler;
target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
act.sa_flags = old_act->sa_flags;
@@ -2737,6 +2816,7 @@
if (!is_error(ret) && arg3) {
lock_user_struct(old_act, arg3, 0);
+ if( ret=page_check_range(old_act,sizeof(*old_act),PAGE_WRITE) ) return -ret;
old_act->_sa_handler = oact._sa_handler;
old_act->sa_flags = oact.sa_flags;
old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
@@ -2753,12 +2833,16 @@
struct target_sigaction *act;
struct target_sigaction *oact;
- if (arg2)
+ if (arg2) {
lock_user_struct(act, arg2, 1);
+ if( ret=page_check_range(act,sizeof(*act),PAGE_READ) ) return -ret;
+ }
else
act = NULL;
- if (arg3)
+ if (arg3) {
lock_user_struct(oact, arg3, 0);
+ if( ret=page_check_range(oact,sizeof(*oact),PAGE_WRITE) ) return -ret;
+ }
else
oact = NULL;
ret = get_errno(do_sigaction(arg1, act, oact));
@@ -2878,6 +2962,7 @@
ret = get_errno(sigpending(&set));
if (!is_error(ret)) {
p = lock_user(arg1, sizeof(target_sigset_t), 0);
+ if( ret=page_check_range(p,sizeof(target_sigset_t),PAGE_WRITE) ) return -ret;
host_to_target_sigset(p, &set);
unlock_user(p, arg1, sizeof(target_sigset_t));
}
@@ -3341,6 +3426,7 @@
struct target_stat *target_st;
lock_user_struct(target_st, arg2, 0);
+ if( ret=page_check_range(target_st,sizeof(*target_st),PAGE_WRITE) ) return -ret;
target_st->st_dev = tswap16(st.st_dev);
target_st->st_ino = tswapl(st.st_ino);
#if defined(TARGET_PPC) || defined(TARGET_MIPS)
@@ -3840,6 +3926,7 @@
#ifdef TARGET_NR_stat64
case TARGET_NR_stat64:
p = lock_user_string(arg1);
+ if( ret=page_check_range(p,1,PAGE_READ) ) return -ret;
ret = get_errno(stat(path(p), &st));
unlock_user(p, arg1, 0);
goto do_stat64;
@@ -3847,6 +3934,7 @@
#ifdef TARGET_NR_lstat64
case TARGET_NR_lstat64:
p = lock_user_string(arg1);
+ if( ret=page_check_range(p,1,PAGE_READ) ) return -ret;
ret = get_errno(lstat(path(p), &st));
unlock_user(p, arg1, 0);
goto do_stat64;
@@ -3861,6 +3949,7 @@
if (((CPUARMState *)cpu_env)->eabi) {
struct target_eabi_stat64 *target_st;
lock_user_struct(target_st, arg2, 1);
+ if( ret=page_check_range(target_st,sizeof(*target_st),PAGE_WRITE) ) return -ret;
memset(target_st, 0, sizeof(struct target_eabi_stat64));
/* put_user is probably wrong. */
put_user(st.st_dev, &target_st->st_dev);
@@ -3886,6 +3975,7 @@
{
struct target_stat64 *target_st;
lock_user_struct(target_st, arg2, 1);
+ if( ret=page_check_range(target_st,sizeof(*target_st),PAGE_WRITE) ) return -ret;
memset(target_st, 0, sizeof(struct target_stat64));
/* ??? put_user is probably wrong. */
put_user(st.st_dev, &target_st->st_dev);