[PATCH] pSeries: hvsi char driver janitorial cleanup
[linux-2.6] / ipc / shm.c
1 /*
2  * linux/ipc/shm.c
3  * Copyright (C) 1992, 1993 Krishna Balasubramanian
4  *       Many improvements/fixes by Bruno Haible.
5  * Replaced `struct shm_desc' by `struct vm_area_struct', July 1994.
6  * Fixed the shm swap deallocation (shm_unuse()), August 1998 Andrea Arcangeli.
7  *
8  * /proc/sysvipc/shm support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
9  * BIGMEM support, Andrea Arcangeli <andrea@suse.de>
10  * SMP thread shm, Jean-Luc Boyard <jean-luc.boyard@siemens.fr>
11  * HIGHMEM support, Ingo Molnar <mingo@redhat.com>
12  * Make shmmax, shmall, shmmni sysctl'able, Christoph Rohland <cr@sap.com>
13  * Shared /dev/zero support, Kanoj Sarcar <kanoj@sgi.com>
14  * Move the mm functionality over to mm/shmem.c, Christoph Rohland <cr@sap.com>
15  *
16  * support for audit of ipc object properties and permission changes
17  * Dustin Kirkland <dustin.kirkland@us.ibm.com>
18  */
19
20 #include <linux/slab.h>
21 #include <linux/mm.h>
22 #include <linux/hugetlb.h>
23 #include <linux/shm.h>
24 #include <linux/init.h>
25 #include <linux/file.h>
26 #include <linux/mman.h>
27 #include <linux/shmem_fs.h>
28 #include <linux/security.h>
29 #include <linux/syscalls.h>
30 #include <linux/audit.h>
31 #include <linux/capability.h>
32 #include <linux/ptrace.h>
33 #include <linux/seq_file.h>
34 #include <linux/mutex.h>
35
36 #include <asm/uaccess.h>
37
38 #include "util.h"
39
40 static struct file_operations shm_file_operations;
41 static struct vm_operations_struct shm_vm_ops;
42
43 static struct ipc_ids shm_ids;
44
45 #define shm_lock(id)    ((struct shmid_kernel*)ipc_lock(&shm_ids,id))
46 #define shm_unlock(shp) ipc_unlock(&(shp)->shm_perm)
47 #define shm_get(id)     ((struct shmid_kernel*)ipc_get(&shm_ids,id))
48 #define shm_buildid(id, seq) \
49         ipc_buildid(&shm_ids, id, seq)
50
51 static int newseg (key_t key, int shmflg, size_t size);
52 static void shm_open (struct vm_area_struct *shmd);
53 static void shm_close (struct vm_area_struct *shmd);
54 #ifdef CONFIG_PROC_FS
55 static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
56 #endif
57
58 size_t  shm_ctlmax = SHMMAX;
59 size_t  shm_ctlall = SHMALL;
60 int     shm_ctlmni = SHMMNI;
61
62 static int shm_tot; /* total number of shared memory pages */
63
64 void __init shm_init (void)
65 {
66         ipc_init_ids(&shm_ids, 1);
67         ipc_init_proc_interface("sysvipc/shm",
68                                 "       key      shmid perms       size  cpid  lpid nattch   uid   gid  cuid  cgid      atime      dtime      ctime\n",
69                                 &shm_ids,
70                                 sysvipc_shm_proc_show);
71 }
72
73 static inline int shm_checkid(struct shmid_kernel *s, int id)
74 {
75         if (ipc_checkid(&shm_ids,&s->shm_perm,id))
76                 return -EIDRM;
77         return 0;
78 }
79
80 static inline struct shmid_kernel *shm_rmid(int id)
81 {
82         return (struct shmid_kernel *)ipc_rmid(&shm_ids,id);
83 }
84
85 static inline int shm_addid(struct shmid_kernel *shp)
86 {
87         return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni);
88 }
89
90
91
92 static inline void shm_inc (int id) {
93         struct shmid_kernel *shp;
94
95         shp = shm_lock(id);
96         BUG_ON(!shp);
97         shp->shm_atim = get_seconds();
98         shp->shm_lprid = current->tgid;
99         shp->shm_nattch++;
100         shm_unlock(shp);
101 }
102
103 /* This is called by fork, once for every shm attach. */
104 static void shm_open (struct vm_area_struct *shmd)
105 {
106         shm_inc (shmd->vm_file->f_dentry->d_inode->i_ino);
107 }
108
109 /*
110  * shm_destroy - free the struct shmid_kernel
111  *
112  * @shp: struct to free
113  *
114  * It has to be called with shp and shm_ids.mutex locked,
115  * but returns with shp unlocked and freed.
116  */
117 static void shm_destroy (struct shmid_kernel *shp)
118 {
119         shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT;
120         shm_rmid (shp->id);
121         shm_unlock(shp);
122         if (!is_file_hugepages(shp->shm_file))
123                 shmem_lock(shp->shm_file, 0, shp->mlock_user);
124         else
125                 user_shm_unlock(shp->shm_file->f_dentry->d_inode->i_size,
126                                                 shp->mlock_user);
127         fput (shp->shm_file);
128         security_shm_free(shp);
129         ipc_rcu_putref(shp);
130 }
131
132 /*
133  * remove the attach descriptor shmd.
134  * free memory for segment if it is marked destroyed.
135  * The descriptor has already been removed from the current->mm->mmap list
136  * and will later be kfree()d.
137  */
138 static void shm_close (struct vm_area_struct *shmd)
139 {
140         struct file * file = shmd->vm_file;
141         int id = file->f_dentry->d_inode->i_ino;
142         struct shmid_kernel *shp;
143
144         mutex_lock(&shm_ids.mutex);
145         /* remove from the list of attaches of the shm segment */
146         shp = shm_lock(id);
147         BUG_ON(!shp);
148         shp->shm_lprid = current->tgid;
149         shp->shm_dtim = get_seconds();
150         shp->shm_nattch--;
151         if(shp->shm_nattch == 0 &&
152            shp->shm_perm.mode & SHM_DEST)
153                 shm_destroy (shp);
154         else
155                 shm_unlock(shp);
156         mutex_unlock(&shm_ids.mutex);
157 }
158
159 static int shm_mmap(struct file * file, struct vm_area_struct * vma)
160 {
161         int ret;
162
163         ret = shmem_mmap(file, vma);
164         if (ret == 0) {
165                 vma->vm_ops = &shm_vm_ops;
166                 if (!(vma->vm_flags & VM_WRITE))
167                         vma->vm_flags &= ~VM_MAYWRITE;
168                 shm_inc(file->f_dentry->d_inode->i_ino);
169         }
170
171         return ret;
172 }
173
174 static struct file_operations shm_file_operations = {
175         .mmap   = shm_mmap,
176 #ifndef CONFIG_MMU
177         .get_unmapped_area = shmem_get_unmapped_area,
178 #endif
179 };
180
181 static struct vm_operations_struct shm_vm_ops = {
182         .open   = shm_open,     /* callback for a new vm-area open */
183         .close  = shm_close,    /* callback for when the vm-area is released */
184         .nopage = shmem_nopage,
185 #if defined(CONFIG_NUMA) && defined(CONFIG_SHMEM)
186         .set_policy = shmem_set_policy,
187         .get_policy = shmem_get_policy,
188 #endif
189 };
190
191 static int newseg (key_t key, int shmflg, size_t size)
192 {
193         int error;
194         struct shmid_kernel *shp;
195         int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT;
196         struct file * file;
197         char name[13];
198         int id;
199
200         if (size < SHMMIN || size > shm_ctlmax)
201                 return -EINVAL;
202
203         if (shm_tot + numpages >= shm_ctlall)
204                 return -ENOSPC;
205
206         shp = ipc_rcu_alloc(sizeof(*shp));
207         if (!shp)
208                 return -ENOMEM;
209
210         shp->shm_perm.key = key;
211         shp->shm_perm.mode = (shmflg & S_IRWXUGO);
212         shp->mlock_user = NULL;
213
214         shp->shm_perm.security = NULL;
215         error = security_shm_alloc(shp);
216         if (error) {
217                 ipc_rcu_putref(shp);
218                 return error;
219         }
220
221         if (shmflg & SHM_HUGETLB) {
222                 /* hugetlb_zero_setup takes care of mlock user accounting */
223                 file = hugetlb_zero_setup(size);
224                 shp->mlock_user = current->user;
225         } else {
226                 int acctflag = VM_ACCOUNT;
227                 /*
228                  * Do not allow no accounting for OVERCOMMIT_NEVER, even
229                  * if it's asked for.
230                  */
231                 if  ((shmflg & SHM_NORESERVE) &&
232                                 sysctl_overcommit_memory != OVERCOMMIT_NEVER)
233                         acctflag = 0;
234                 sprintf (name, "SYSV%08x", key);
235                 file = shmem_file_setup(name, size, acctflag);
236         }
237         error = PTR_ERR(file);
238         if (IS_ERR(file))
239                 goto no_file;
240
241         error = -ENOSPC;
242         id = shm_addid(shp);
243         if(id == -1) 
244                 goto no_id;
245
246         shp->shm_cprid = current->tgid;
247         shp->shm_lprid = 0;
248         shp->shm_atim = shp->shm_dtim = 0;
249         shp->shm_ctim = get_seconds();
250         shp->shm_segsz = size;
251         shp->shm_nattch = 0;
252         shp->id = shm_buildid(id,shp->shm_perm.seq);
253         shp->shm_file = file;
254         file->f_dentry->d_inode->i_ino = shp->id;
255
256         /* Hugetlb ops would have already been assigned. */
257         if (!(shmflg & SHM_HUGETLB))
258                 file->f_op = &shm_file_operations;
259
260         shm_tot += numpages;
261         shm_unlock(shp);
262         return shp->id;
263
264 no_id:
265         fput(file);
266 no_file:
267         security_shm_free(shp);
268         ipc_rcu_putref(shp);
269         return error;
270 }
271
272 asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
273 {
274         struct shmid_kernel *shp;
275         int err, id = 0;
276
277         mutex_lock(&shm_ids.mutex);
278         if (key == IPC_PRIVATE) {
279                 err = newseg(key, shmflg, size);
280         } else if ((id = ipc_findkey(&shm_ids, key)) == -1) {
281                 if (!(shmflg & IPC_CREAT))
282                         err = -ENOENT;
283                 else
284                         err = newseg(key, shmflg, size);
285         } else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) {
286                 err = -EEXIST;
287         } else {
288                 shp = shm_lock(id);
289                 BUG_ON(shp==NULL);
290                 if (shp->shm_segsz < size)
291                         err = -EINVAL;
292                 else if (ipcperms(&shp->shm_perm, shmflg))
293                         err = -EACCES;
294                 else {
295                         int shmid = shm_buildid(id, shp->shm_perm.seq);
296                         err = security_shm_associate(shp, shmflg);
297                         if (!err)
298                                 err = shmid;
299                 }
300                 shm_unlock(shp);
301         }
302         mutex_unlock(&shm_ids.mutex);
303
304         return err;
305 }
306
307 static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_ds *in, int version)
308 {
309         switch(version) {
310         case IPC_64:
311                 return copy_to_user(buf, in, sizeof(*in));
312         case IPC_OLD:
313             {
314                 struct shmid_ds out;
315
316                 ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm);
317                 out.shm_segsz   = in->shm_segsz;
318                 out.shm_atime   = in->shm_atime;
319                 out.shm_dtime   = in->shm_dtime;
320                 out.shm_ctime   = in->shm_ctime;
321                 out.shm_cpid    = in->shm_cpid;
322                 out.shm_lpid    = in->shm_lpid;
323                 out.shm_nattch  = in->shm_nattch;
324
325                 return copy_to_user(buf, &out, sizeof(out));
326             }
327         default:
328                 return -EINVAL;
329         }
330 }
331
332 struct shm_setbuf {
333         uid_t   uid;
334         gid_t   gid;
335         mode_t  mode;
336 };      
337
338 static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void __user *buf, int version)
339 {
340         switch(version) {
341         case IPC_64:
342             {
343                 struct shmid64_ds tbuf;
344
345                 if (copy_from_user(&tbuf, buf, sizeof(tbuf)))
346                         return -EFAULT;
347
348                 out->uid        = tbuf.shm_perm.uid;
349                 out->gid        = tbuf.shm_perm.gid;
350                 out->mode       = tbuf.shm_perm.mode;
351
352                 return 0;
353             }
354         case IPC_OLD:
355             {
356                 struct shmid_ds tbuf_old;
357
358                 if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
359                         return -EFAULT;
360
361                 out->uid        = tbuf_old.shm_perm.uid;
362                 out->gid        = tbuf_old.shm_perm.gid;
363                 out->mode       = tbuf_old.shm_perm.mode;
364
365                 return 0;
366             }
367         default:
368                 return -EINVAL;
369         }
370 }
371
372 static inline unsigned long copy_shminfo_to_user(void __user *buf, struct shminfo64 *in, int version)
373 {
374         switch(version) {
375         case IPC_64:
376                 return copy_to_user(buf, in, sizeof(*in));
377         case IPC_OLD:
378             {
379                 struct shminfo out;
380
381                 if(in->shmmax > INT_MAX)
382                         out.shmmax = INT_MAX;
383                 else
384                         out.shmmax = (int)in->shmmax;
385
386                 out.shmmin      = in->shmmin;
387                 out.shmmni      = in->shmmni;
388                 out.shmseg      = in->shmseg;
389                 out.shmall      = in->shmall; 
390
391                 return copy_to_user(buf, &out, sizeof(out));
392             }
393         default:
394                 return -EINVAL;
395         }
396 }
397
398 static void shm_get_stat(unsigned long *rss, unsigned long *swp) 
399 {
400         int i;
401
402         *rss = 0;
403         *swp = 0;
404
405         for (i = 0; i <= shm_ids.max_id; i++) {
406                 struct shmid_kernel *shp;
407                 struct inode *inode;
408
409                 shp = shm_get(i);
410                 if(!shp)
411                         continue;
412
413                 inode = shp->shm_file->f_dentry->d_inode;
414
415                 if (is_file_hugepages(shp->shm_file)) {
416                         struct address_space *mapping = inode->i_mapping;
417                         *rss += (HPAGE_SIZE/PAGE_SIZE)*mapping->nrpages;
418                 } else {
419                         struct shmem_inode_info *info = SHMEM_I(inode);
420                         spin_lock(&info->lock);
421                         *rss += inode->i_mapping->nrpages;
422                         *swp += info->swapped;
423                         spin_unlock(&info->lock);
424                 }
425         }
426 }
427
428 asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
429 {
430         struct shm_setbuf setbuf;
431         struct shmid_kernel *shp;
432         int err, version;
433
434         if (cmd < 0 || shmid < 0) {
435                 err = -EINVAL;
436                 goto out;
437         }
438
439         version = ipc_parse_version(&cmd);
440
441         switch (cmd) { /* replace with proc interface ? */
442         case IPC_INFO:
443         {
444                 struct shminfo64 shminfo;
445
446                 err = security_shm_shmctl(NULL, cmd);
447                 if (err)
448                         return err;
449
450                 memset(&shminfo,0,sizeof(shminfo));
451                 shminfo.shmmni = shminfo.shmseg = shm_ctlmni;
452                 shminfo.shmmax = shm_ctlmax;
453                 shminfo.shmall = shm_ctlall;
454
455                 shminfo.shmmin = SHMMIN;
456                 if(copy_shminfo_to_user (buf, &shminfo, version))
457                         return -EFAULT;
458                 /* reading a integer is always atomic */
459                 err= shm_ids.max_id;
460                 if(err<0)
461                         err = 0;
462                 goto out;
463         }
464         case SHM_INFO:
465         {
466                 struct shm_info shm_info;
467
468                 err = security_shm_shmctl(NULL, cmd);
469                 if (err)
470                         return err;
471
472                 memset(&shm_info,0,sizeof(shm_info));
473                 mutex_lock(&shm_ids.mutex);
474                 shm_info.used_ids = shm_ids.in_use;
475                 shm_get_stat (&shm_info.shm_rss, &shm_info.shm_swp);
476                 shm_info.shm_tot = shm_tot;
477                 shm_info.swap_attempts = 0;
478                 shm_info.swap_successes = 0;
479                 err = shm_ids.max_id;
480                 mutex_unlock(&shm_ids.mutex);
481                 if(copy_to_user (buf, &shm_info, sizeof(shm_info))) {
482                         err = -EFAULT;
483                         goto out;
484                 }
485
486                 err = err < 0 ? 0 : err;
487                 goto out;
488         }
489         case SHM_STAT:
490         case IPC_STAT:
491         {
492                 struct shmid64_ds tbuf;
493                 int result;
494                 memset(&tbuf, 0, sizeof(tbuf));
495                 shp = shm_lock(shmid);
496                 if(shp==NULL) {
497                         err = -EINVAL;
498                         goto out;
499                 } else if(cmd==SHM_STAT) {
500                         err = -EINVAL;
501                         if (shmid > shm_ids.max_id)
502                                 goto out_unlock;
503                         result = shm_buildid(shmid, shp->shm_perm.seq);
504                 } else {
505                         err = shm_checkid(shp,shmid);
506                         if(err)
507                                 goto out_unlock;
508                         result = 0;
509                 }
510                 err=-EACCES;
511                 if (ipcperms (&shp->shm_perm, S_IRUGO))
512                         goto out_unlock;
513                 err = security_shm_shmctl(shp, cmd);
514                 if (err)
515                         goto out_unlock;
516                 kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);
517                 tbuf.shm_segsz  = shp->shm_segsz;
518                 tbuf.shm_atime  = shp->shm_atim;
519                 tbuf.shm_dtime  = shp->shm_dtim;
520                 tbuf.shm_ctime  = shp->shm_ctim;
521                 tbuf.shm_cpid   = shp->shm_cprid;
522                 tbuf.shm_lpid   = shp->shm_lprid;
523                 if (!is_file_hugepages(shp->shm_file))
524                         tbuf.shm_nattch = shp->shm_nattch;
525                 else
526                         tbuf.shm_nattch = file_count(shp->shm_file) - 1;
527                 shm_unlock(shp);
528                 if(copy_shmid_to_user (buf, &tbuf, version))
529                         err = -EFAULT;
530                 else
531                         err = result;
532                 goto out;
533         }
534         case SHM_LOCK:
535         case SHM_UNLOCK:
536         {
537                 shp = shm_lock(shmid);
538                 if(shp==NULL) {
539                         err = -EINVAL;
540                         goto out;
541                 }
542                 err = shm_checkid(shp,shmid);
543                 if(err)
544                         goto out_unlock;
545
546                 err = audit_ipc_obj(&(shp->shm_perm));
547                 if (err)
548                         goto out_unlock;
549
550                 if (!capable(CAP_IPC_LOCK)) {
551                         err = -EPERM;
552                         if (current->euid != shp->shm_perm.uid &&
553                             current->euid != shp->shm_perm.cuid)
554                                 goto out_unlock;
555                         if (cmd == SHM_LOCK &&
556                             !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
557                                 goto out_unlock;
558                 }
559
560                 err = security_shm_shmctl(shp, cmd);
561                 if (err)
562                         goto out_unlock;
563                 
564                 if(cmd==SHM_LOCK) {
565                         struct user_struct * user = current->user;
566                         if (!is_file_hugepages(shp->shm_file)) {
567                                 err = shmem_lock(shp->shm_file, 1, user);
568                                 if (!err) {
569                                         shp->shm_perm.mode |= SHM_LOCKED;
570                                         shp->mlock_user = user;
571                                 }
572                         }
573                 } else if (!is_file_hugepages(shp->shm_file)) {
574                         shmem_lock(shp->shm_file, 0, shp->mlock_user);
575                         shp->shm_perm.mode &= ~SHM_LOCKED;
576                         shp->mlock_user = NULL;
577                 }
578                 shm_unlock(shp);
579                 goto out;
580         }
581         case IPC_RMID:
582         {
583                 /*
584                  *      We cannot simply remove the file. The SVID states
585                  *      that the block remains until the last person
586                  *      detaches from it, then is deleted. A shmat() on
587                  *      an RMID segment is legal in older Linux and if 
588                  *      we change it apps break...
589                  *
590                  *      Instead we set a destroyed flag, and then blow
591                  *      the name away when the usage hits zero.
592                  */
593                 mutex_lock(&shm_ids.mutex);
594                 shp = shm_lock(shmid);
595                 err = -EINVAL;
596                 if (shp == NULL) 
597                         goto out_up;
598                 err = shm_checkid(shp, shmid);
599                 if(err)
600                         goto out_unlock_up;
601
602                 err = audit_ipc_obj(&(shp->shm_perm));
603                 if (err)
604                         goto out_unlock_up;
605
606                 if (current->euid != shp->shm_perm.uid &&
607                     current->euid != shp->shm_perm.cuid && 
608                     !capable(CAP_SYS_ADMIN)) {
609                         err=-EPERM;
610                         goto out_unlock_up;
611                 }
612
613                 err = security_shm_shmctl(shp, cmd);
614                 if (err)
615                         goto out_unlock_up;
616
617                 if (shp->shm_nattch){
618                         shp->shm_perm.mode |= SHM_DEST;
619                         /* Do not find it any more */
620                         shp->shm_perm.key = IPC_PRIVATE;
621                         shm_unlock(shp);
622                 } else
623                         shm_destroy (shp);
624                 mutex_unlock(&shm_ids.mutex);
625                 goto out;
626         }
627
628         case IPC_SET:
629         {
630                 if (copy_shmid_from_user (&setbuf, buf, version)) {
631                         err = -EFAULT;
632                         goto out;
633                 }
634                 mutex_lock(&shm_ids.mutex);
635                 shp = shm_lock(shmid);
636                 err=-EINVAL;
637                 if(shp==NULL)
638                         goto out_up;
639                 err = shm_checkid(shp,shmid);
640                 if(err)
641                         goto out_unlock_up;
642                 err = audit_ipc_obj(&(shp->shm_perm));
643                 if (err)
644                         goto out_unlock_up;
645                 err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode);
646                 if (err)
647                         goto out_unlock_up;
648                 err=-EPERM;
649                 if (current->euid != shp->shm_perm.uid &&
650                     current->euid != shp->shm_perm.cuid && 
651                     !capable(CAP_SYS_ADMIN)) {
652                         goto out_unlock_up;
653                 }
654
655                 err = security_shm_shmctl(shp, cmd);
656                 if (err)
657                         goto out_unlock_up;
658                 
659                 shp->shm_perm.uid = setbuf.uid;
660                 shp->shm_perm.gid = setbuf.gid;
661                 shp->shm_perm.mode = (shp->shm_perm.mode & ~S_IRWXUGO)
662                         | (setbuf.mode & S_IRWXUGO);
663                 shp->shm_ctim = get_seconds();
664                 break;
665         }
666
667         default:
668                 err = -EINVAL;
669                 goto out;
670         }
671
672         err = 0;
673 out_unlock_up:
674         shm_unlock(shp);
675 out_up:
676         mutex_unlock(&shm_ids.mutex);
677         goto out;
678 out_unlock:
679         shm_unlock(shp);
680 out:
681         return err;
682 }
683
684 /*
685  * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists.
686  *
687  * NOTE! Despite the name, this is NOT a direct system call entrypoint. The
688  * "raddr" thing points to kernel space, and there has to be a wrapper around
689  * this.
690  */
691 long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
692 {
693         struct shmid_kernel *shp;
694         unsigned long addr;
695         unsigned long size;
696         struct file * file;
697         int    err;
698         unsigned long flags;
699         unsigned long prot;
700         int acc_mode;
701         void *user_addr;
702
703         if (shmid < 0) {
704                 err = -EINVAL;
705                 goto out;
706         } else if ((addr = (ulong)shmaddr)) {
707                 if (addr & (SHMLBA-1)) {
708                         if (shmflg & SHM_RND)
709                                 addr &= ~(SHMLBA-1);       /* round down */
710                         else
711 #ifndef __ARCH_FORCE_SHMLBA
712                                 if (addr & ~PAGE_MASK)
713 #endif
714                                         return -EINVAL;
715                 }
716                 flags = MAP_SHARED | MAP_FIXED;
717         } else {
718                 if ((shmflg & SHM_REMAP))
719                         return -EINVAL;
720
721                 flags = MAP_SHARED;
722         }
723
724         if (shmflg & SHM_RDONLY) {
725                 prot = PROT_READ;
726                 acc_mode = S_IRUGO;
727         } else {
728                 prot = PROT_READ | PROT_WRITE;
729                 acc_mode = S_IRUGO | S_IWUGO;
730         }
731         if (shmflg & SHM_EXEC) {
732                 prot |= PROT_EXEC;
733                 acc_mode |= S_IXUGO;
734         }
735
736         /*
737          * We cannot rely on the fs check since SYSV IPC does have an
738          * additional creator id...
739          */
740         shp = shm_lock(shmid);
741         if(shp == NULL) {
742                 err = -EINVAL;
743                 goto out;
744         }
745         err = shm_checkid(shp,shmid);
746         if (err) {
747                 shm_unlock(shp);
748                 goto out;
749         }
750         if (ipcperms(&shp->shm_perm, acc_mode)) {
751                 shm_unlock(shp);
752                 err = -EACCES;
753                 goto out;
754         }
755
756         err = security_shm_shmat(shp, shmaddr, shmflg);
757         if (err) {
758                 shm_unlock(shp);
759                 return err;
760         }
761                 
762         file = shp->shm_file;
763         size = i_size_read(file->f_dentry->d_inode);
764         shp->shm_nattch++;
765         shm_unlock(shp);
766
767         down_write(&current->mm->mmap_sem);
768         if (addr && !(shmflg & SHM_REMAP)) {
769                 user_addr = ERR_PTR(-EINVAL);
770                 if (find_vma_intersection(current->mm, addr, addr + size))
771                         goto invalid;
772                 /*
773                  * If shm segment goes below stack, make sure there is some
774                  * space left for the stack to grow (at least 4 pages).
775                  */
776                 if (addr < current->mm->start_stack &&
777                     addr > current->mm->start_stack - size - PAGE_SIZE * 5)
778                         goto invalid;
779         }
780                 
781         user_addr = (void*) do_mmap (file, addr, size, prot, flags, 0);
782
783 invalid:
784         up_write(&current->mm->mmap_sem);
785
786         mutex_lock(&shm_ids.mutex);
787         shp = shm_lock(shmid);
788         BUG_ON(!shp);
789         shp->shm_nattch--;
790         if(shp->shm_nattch == 0 &&
791            shp->shm_perm.mode & SHM_DEST)
792                 shm_destroy (shp);
793         else
794                 shm_unlock(shp);
795         mutex_unlock(&shm_ids.mutex);
796
797         *raddr = (unsigned long) user_addr;
798         err = 0;
799         if (IS_ERR(user_addr))
800                 err = PTR_ERR(user_addr);
801 out:
802         return err;
803 }
804
805 asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg)
806 {
807         unsigned long ret;
808         long err;
809
810         err = do_shmat(shmid, shmaddr, shmflg, &ret);
811         if (err)
812                 return err;
813         force_successful_syscall_return();
814         return (long)ret;
815 }
816
817 /*
818  * detach and kill segment if marked destroyed.
819  * The work is done in shm_close.
820  */
821 asmlinkage long sys_shmdt(char __user *shmaddr)
822 {
823         struct mm_struct *mm = current->mm;
824         struct vm_area_struct *vma, *next;
825         unsigned long addr = (unsigned long)shmaddr;
826         loff_t size = 0;
827         int retval = -EINVAL;
828
829         if (addr & ~PAGE_MASK)
830                 return retval;
831
832         down_write(&mm->mmap_sem);
833
834         /*
835          * This function tries to be smart and unmap shm segments that
836          * were modified by partial mlock or munmap calls:
837          * - It first determines the size of the shm segment that should be
838          *   unmapped: It searches for a vma that is backed by shm and that
839          *   started at address shmaddr. It records it's size and then unmaps
840          *   it.
841          * - Then it unmaps all shm vmas that started at shmaddr and that
842          *   are within the initially determined size.
843          * Errors from do_munmap are ignored: the function only fails if
844          * it's called with invalid parameters or if it's called to unmap
845          * a part of a vma. Both calls in this function are for full vmas,
846          * the parameters are directly copied from the vma itself and always
847          * valid - therefore do_munmap cannot fail. (famous last words?)
848          */
849         /*
850          * If it had been mremap()'d, the starting address would not
851          * match the usual checks anyway. So assume all vma's are
852          * above the starting address given.
853          */
854         vma = find_vma(mm, addr);
855
856         while (vma) {
857                 next = vma->vm_next;
858
859                 /*
860                  * Check if the starting address would match, i.e. it's
861                  * a fragment created by mprotect() and/or munmap(), or it
862                  * otherwise it starts at this address with no hassles.
863                  */
864                 if ((vma->vm_ops == &shm_vm_ops || is_vm_hugetlb_page(vma)) &&
865                         (vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) {
866
867
868                         size = vma->vm_file->f_dentry->d_inode->i_size;
869                         do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
870                         /*
871                          * We discovered the size of the shm segment, so
872                          * break out of here and fall through to the next
873                          * loop that uses the size information to stop
874                          * searching for matching vma's.
875                          */
876                         retval = 0;
877                         vma = next;
878                         break;
879                 }
880                 vma = next;
881         }
882
883         /*
884          * We need look no further than the maximum address a fragment
885          * could possibly have landed at. Also cast things to loff_t to
886          * prevent overflows and make comparisions vs. equal-width types.
887          */
888         size = PAGE_ALIGN(size);
889         while (vma && (loff_t)(vma->vm_end - addr) <= size) {
890                 next = vma->vm_next;
891
892                 /* finding a matching vma now does not alter retval */
893                 if ((vma->vm_ops == &shm_vm_ops || is_vm_hugetlb_page(vma)) &&
894                         (vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff)
895
896                         do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
897                 vma = next;
898         }
899
900         up_write(&mm->mmap_sem);
901         return retval;
902 }
903
904 #ifdef CONFIG_PROC_FS
905 static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
906 {
907         struct shmid_kernel *shp = it;
908         char *format;
909
910 #define SMALL_STRING "%10d %10d  %4o %10u %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
911 #define BIG_STRING   "%10d %10d  %4o %21u %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
912
913         if (sizeof(size_t) <= sizeof(int))
914                 format = SMALL_STRING;
915         else
916                 format = BIG_STRING;
917         return seq_printf(s, format,
918                           shp->shm_perm.key,
919                           shp->id,
920                           shp->shm_perm.mode,
921                           shp->shm_segsz,
922                           shp->shm_cprid,
923                           shp->shm_lprid,
924                           is_file_hugepages(shp->shm_file) ? (file_count(shp->shm_file) - 1) : shp->shm_nattch,
925                           shp->shm_perm.uid,
926                           shp->shm_perm.gid,
927                           shp->shm_perm.cuid,
928                           shp->shm_perm.cgid,
929                           shp->shm_atim,
930                           shp->shm_dtim,
931                           shp->shm_ctim);
932 }
933 #endif