patch-2.3.39 linux/ipc/shm.c
Next file: linux/ipc/util.c
Previous file: linux/ipc/sem.c
Back to the patch index
Back to the overall index
- Lines: 225
- Date:
Mon Jan 10 18:15:58 2000
- Orig file:
v2.3.38/linux/ipc/shm.c
- Orig date:
Fri Jan 7 19:13:23 2000
diff -u --recursive --new-file v2.3.38/linux/ipc/shm.c linux/ipc/shm.c
@@ -29,9 +29,18 @@
#include "util.h"
-struct shmid_kernel /* extend struct shmis_ds with private fields */
+struct shmid_kernel /* private to the kernel */
{
- struct shmid_ds u;
+ struct {
+ struct kern_ipc_perm shm_perm;
+ size_t shm_segsz;
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
+ pid_t shm_cpid;
+ pid_t shm_lpid;
+ unsigned long shm_nattch;
+ } u;
unsigned long shm_npages; /* size of segment (pages) */
pte_t **shm_dir; /* ptr to array of ptrs to frames -> SHMMAX */
struct vm_area_struct *attaches; /* descriptors for attaches */
@@ -89,7 +98,6 @@
/* some statistics */
static ulong swap_attempts = 0;
static ulong swap_successes = 0;
-static ulong used_segs = 0;
void __init shm_init (void)
{
@@ -303,19 +311,112 @@
return;
}
+static inline unsigned long copy_shmid_to_user(void *buf, struct shmid64_ds *in, int version)
+{
+ switch(version) {
+ case IPC_64:
+ return copy_to_user(buf, in, sizeof(*in));
+ case IPC_OLD:
+ {
+ struct shmid_ds out;
+
+ ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm);
+ out.shm_segsz = in->shm_segsz;
+ out.shm_atime = in->shm_atime;
+ out.shm_dtime = in->shm_dtime;
+ out.shm_ctime = in->shm_ctime;
+ out.shm_cpid = in->shm_cpid;
+ out.shm_lpid = in->shm_lpid;
+ out.shm_nattch = in->shm_nattch;
+
+ return copy_to_user(buf, &out, sizeof(out));
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+struct shm_setbuf {
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+};
+
+static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void *buf, int version)
+{
+ switch(version) {
+ case IPC_64:
+ {
+ struct shmid64_ds tbuf;
+
+ if (copy_from_user(&tbuf, buf, sizeof(tbuf)))
+ return -EFAULT;
+
+ out->uid = tbuf.shm_perm.uid;
+ out->gid = tbuf.shm_perm.gid;
+ out->mode = tbuf.shm_perm.mode;
+
+ return 0;
+ }
+ case IPC_OLD:
+ {
+ struct shmid_ds tbuf_old;
+
+ if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
+ return -EFAULT;
+
+ out->uid = tbuf_old.shm_perm.uid;
+ out->gid = tbuf_old.shm_perm.gid;
+ out->mode = tbuf_old.shm_perm.mode;
+
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static inline unsigned long copy_shminfo_to_user(void *buf, struct shminfo64 *in, int version)
+{
+ switch(version) {
+ case IPC_64:
+ return copy_to_user(buf, in, sizeof(*in));
+ case IPC_OLD:
+ {
+ struct shminfo out;
+
+ if(in->shmmax > INT_MAX)
+ out.shmmax = INT_MAX;
+ else
+ out.shmmax = (int)in->shmmax;
+
+ out.shmmin = in->shmmin;
+ out.shmmni = in->shmmni;
+ out.shmseg = in->shmseg;
+ out.shmall = in->shmall;
+
+ return copy_to_user(buf, &out, sizeof(out));
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
{
- struct shmid_ds tbuf;
+ struct shm_setbuf setbuf;
struct shmid_kernel *shp;
- int err;
+ int err, version;
if (cmd < 0 || shmid < 0)
return -EINVAL;
+ version = ipc_parse_version(&cmd);
+
switch (cmd) { /* replace with proc interface ? */
case IPC_INFO:
{
- struct shminfo shminfo;
+ struct shminfo64 shminfo;
memset(&shminfo,0,sizeof(shminfo));
shminfo.shmmni = shminfo.shmseg = shm_ctlmni;
@@ -323,7 +424,7 @@
shminfo.shmall = shm_ctlall;
shminfo.shmmin = SHMMIN;
- if(copy_to_user (buf, &shminfo, sizeof(struct shminfo)))
+ if(copy_shminfo_to_user (buf, &shminfo, version))
return -EFAULT;
/* reading a integer is always atomic */
err= shm_ids.max_id;
@@ -337,7 +438,7 @@
memset(&shm_info,0,sizeof(shm_info));
shm_lockall();
- shm_info.used_ids = used_segs;
+ shm_info.used_ids = shm_ids.in_use;
shm_info.shm_rss = shm_rss;
shm_info.shm_tot = shm_tot;
shm_info.shm_swp = shm_swp;
@@ -353,8 +454,9 @@
case SHM_STAT:
case IPC_STAT:
{
- struct shmid_ds tmp;
+ struct shmid64_ds tbuf;
int result;
+ memset(&tbuf, 0, sizeof(tbuf));
shp = shm_lock(shmid);
if(shp==NULL)
return -EINVAL;
@@ -372,9 +474,16 @@
err=-EACCES;
if (ipcperms (&shp->u.shm_perm, S_IRUGO))
goto out_unlock;
- memcpy(&tmp,&shp->u,sizeof(tmp));
+ kernel_to_ipc64_perm(&shp->u.shm_perm, &tbuf.shm_perm);
+ tbuf.shm_segsz = shp->u.shm_segsz;
+ tbuf.shm_atime = shp->u.shm_atime;
+ tbuf.shm_dtime = shp->u.shm_dtime;
+ tbuf.shm_ctime = shp->u.shm_ctime;
+ tbuf.shm_cpid = shp->u.shm_cpid;
+ tbuf.shm_lpid = shp->u.shm_lpid;
+ tbuf.shm_nattch = shp->u.shm_nattch;
shm_unlock(shmid);
- if(copy_to_user (buf, &tmp, sizeof(tmp)))
+ if(copy_shmid_to_user (buf, &tbuf, version))
return -EFAULT;
return result;
}
@@ -384,7 +493,7 @@
/* Allow superuser to lock segment in memory */
/* Should the pages be faulted in here or leave it to user? */
/* need to determine interaction with current->swappable */
- struct ipc_perm *ipcp;
+ struct kern_ipc_perm *ipcp;
if (!capable(CAP_IPC_LOCK))
return -EPERM;
@@ -417,7 +526,7 @@
}
if (cmd == IPC_SET) {
- if(copy_from_user (&tbuf, buf, sizeof (*buf)))
+ if(copy_shmid_from_user (&setbuf, buf, version))
return -EFAULT;
}
down(&shm_ids.sem);
@@ -437,10 +546,10 @@
switch (cmd) {
case IPC_SET:
- shp->u.shm_perm.uid = tbuf.shm_perm.uid;
- shp->u.shm_perm.gid = tbuf.shm_perm.gid;
+ shp->u.shm_perm.uid = setbuf.uid;
+ shp->u.shm_perm.gid = setbuf.gid;
shp->u.shm_perm.mode = (shp->u.shm_perm.mode & ~S_IRWXUGO)
- | (tbuf.shm_perm.mode & S_IRWXUGO);
+ | (setbuf.mode & S_IRWXUGO);
shp->u.shm_ctime = CURRENT_TIME;
break;
case IPC_RMID:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)