0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 #include <linux/mm.h>
0048 #include <linux/shm.h>
0049 #include <linux/init.h>
0050 #include <linux/msg.h>
0051 #include <linux/vmalloc.h>
0052 #include <linux/slab.h>
0053 #include <linux/notifier.h>
0054 #include <linux/capability.h>
0055 #include <linux/highuid.h>
0056 #include <linux/security.h>
0057 #include <linux/rcupdate.h>
0058 #include <linux/workqueue.h>
0059 #include <linux/seq_file.h>
0060 #include <linux/proc_fs.h>
0061 #include <linux/audit.h>
0062 #include <linux/nsproxy.h>
0063 #include <linux/rwsem.h>
0064 #include <linux/memory.h>
0065 #include <linux/ipc_namespace.h>
0066 #include <linux/rhashtable.h>
0067 #include <linux/log2.h>
0068
0069 #include <asm/unistd.h>
0070
0071 #include "util.h"
0072
0073 struct ipc_proc_iface {
0074 const char *path;
0075 const char *header;
0076 int ids;
0077 int (*show)(struct seq_file *, void *);
0078 };
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 static int __init ipc_init(void)
0091 {
0092 proc_mkdir("sysvipc", NULL);
0093 sem_init();
0094 msg_init();
0095 shm_init();
0096
0097 return 0;
0098 }
0099 device_initcall(ipc_init);
0100
0101 static const struct rhashtable_params ipc_kht_params = {
0102 .head_offset = offsetof(struct kern_ipc_perm, khtnode),
0103 .key_offset = offsetof(struct kern_ipc_perm, key),
0104 .key_len = sizeof_field(struct kern_ipc_perm, key),
0105 .automatic_shrinking = true,
0106 };
0107
0108
0109
0110
0111
0112
0113
0114
0115 void ipc_init_ids(struct ipc_ids *ids)
0116 {
0117 ids->in_use = 0;
0118 ids->seq = 0;
0119 init_rwsem(&ids->rwsem);
0120 rhashtable_init(&ids->key_ht, &ipc_kht_params);
0121 idr_init(&ids->ipcs_idr);
0122 ids->max_idx = -1;
0123 ids->last_idx = -1;
0124 #ifdef CONFIG_CHECKPOINT_RESTORE
0125 ids->next_id = -1;
0126 #endif
0127 }
0128
0129 #ifdef CONFIG_PROC_FS
0130 static const struct proc_ops sysvipc_proc_ops;
0131
0132
0133
0134
0135
0136
0137
0138 void __init ipc_init_proc_interface(const char *path, const char *header,
0139 int ids, int (*show)(struct seq_file *, void *))
0140 {
0141 struct proc_dir_entry *pde;
0142 struct ipc_proc_iface *iface;
0143
0144 iface = kmalloc(sizeof(*iface), GFP_KERNEL);
0145 if (!iface)
0146 return;
0147 iface->path = path;
0148 iface->header = header;
0149 iface->ids = ids;
0150 iface->show = show;
0151
0152 pde = proc_create_data(path,
0153 S_IRUGO,
0154 NULL,
0155 &sysvipc_proc_ops,
0156 iface);
0157 if (!pde)
0158 kfree(iface);
0159 }
0160 #endif
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172 static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
0173 {
0174 struct kern_ipc_perm *ipcp;
0175
0176 ipcp = rhashtable_lookup_fast(&ids->key_ht, &key,
0177 ipc_kht_params);
0178 if (!ipcp)
0179 return NULL;
0180
0181 rcu_read_lock();
0182 ipc_lock_object(ipcp);
0183 return ipcp;
0184 }
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 static inline int ipc_idr_alloc(struct ipc_ids *ids, struct kern_ipc_perm *new)
0203 {
0204 int idx, next_id = -1;
0205
0206 #ifdef CONFIG_CHECKPOINT_RESTORE
0207 next_id = ids->next_id;
0208 ids->next_id = -1;
0209 #endif
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223 if (next_id < 0) {
0224 int max_idx;
0225
0226 max_idx = max(ids->in_use*3/2, ipc_min_cycle);
0227 max_idx = min(max_idx, ipc_mni);
0228
0229
0230 idx = idr_alloc_cyclic(&ids->ipcs_idr, NULL, 0, max_idx,
0231 GFP_NOWAIT);
0232
0233 if (idx >= 0) {
0234
0235
0236
0237
0238
0239 if (idx <= ids->last_idx) {
0240 ids->seq++;
0241 if (ids->seq >= ipcid_seq_max())
0242 ids->seq = 0;
0243 }
0244 ids->last_idx = idx;
0245
0246 new->seq = ids->seq;
0247
0248
0249
0250
0251 idr_replace(&ids->ipcs_idr, new, idx);
0252 }
0253 } else {
0254 new->seq = ipcid_to_seqx(next_id);
0255 idx = idr_alloc(&ids->ipcs_idr, new, ipcid_to_idx(next_id),
0256 0, GFP_NOWAIT);
0257 }
0258 if (idx >= 0)
0259 new->id = (new->seq << ipcmni_seq_shift()) + idx;
0260 return idx;
0261 }
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278 int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit)
0279 {
0280 kuid_t euid;
0281 kgid_t egid;
0282 int idx, err;
0283
0284
0285 refcount_set(&new->refcount, 1);
0286
0287 if (limit > ipc_mni)
0288 limit = ipc_mni;
0289
0290 if (ids->in_use >= limit)
0291 return -ENOSPC;
0292
0293 idr_preload(GFP_KERNEL);
0294
0295 spin_lock_init(&new->lock);
0296 rcu_read_lock();
0297 spin_lock(&new->lock);
0298
0299 current_euid_egid(&euid, &egid);
0300 new->cuid = new->uid = euid;
0301 new->gid = new->cgid = egid;
0302
0303 new->deleted = false;
0304
0305 idx = ipc_idr_alloc(ids, new);
0306 idr_preload_end();
0307
0308 if (idx >= 0 && new->key != IPC_PRIVATE) {
0309 err = rhashtable_insert_fast(&ids->key_ht, &new->khtnode,
0310 ipc_kht_params);
0311 if (err < 0) {
0312 idr_remove(&ids->ipcs_idr, idx);
0313 idx = err;
0314 }
0315 }
0316 if (idx < 0) {
0317 new->deleted = true;
0318 spin_unlock(&new->lock);
0319 rcu_read_unlock();
0320 return idx;
0321 }
0322
0323 ids->in_use++;
0324 if (idx > ids->max_idx)
0325 ids->max_idx = idx;
0326 return idx;
0327 }
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339 static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
0340 const struct ipc_ops *ops, struct ipc_params *params)
0341 {
0342 int err;
0343
0344 down_write(&ids->rwsem);
0345 err = ops->getnew(ns, params);
0346 up_write(&ids->rwsem);
0347 return err;
0348 }
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365 static int ipc_check_perms(struct ipc_namespace *ns,
0366 struct kern_ipc_perm *ipcp,
0367 const struct ipc_ops *ops,
0368 struct ipc_params *params)
0369 {
0370 int err;
0371
0372 if (ipcperms(ns, ipcp, params->flg))
0373 err = -EACCES;
0374 else {
0375 err = ops->associate(ipcp, params->flg);
0376 if (!err)
0377 err = ipcp->id;
0378 }
0379
0380 return err;
0381 }
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397 static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
0398 const struct ipc_ops *ops, struct ipc_params *params)
0399 {
0400 struct kern_ipc_perm *ipcp;
0401 int flg = params->flg;
0402 int err;
0403
0404
0405
0406
0407
0408 down_write(&ids->rwsem);
0409 ipcp = ipc_findkey(ids, params->key);
0410 if (ipcp == NULL) {
0411
0412 if (!(flg & IPC_CREAT))
0413 err = -ENOENT;
0414 else
0415 err = ops->getnew(ns, params);
0416 } else {
0417
0418
0419 if (flg & IPC_CREAT && flg & IPC_EXCL)
0420 err = -EEXIST;
0421 else {
0422 err = 0;
0423 if (ops->more_checks)
0424 err = ops->more_checks(ipcp, params);
0425 if (!err)
0426
0427
0428
0429
0430 err = ipc_check_perms(ns, ipcp, ops, params);
0431 }
0432 ipc_unlock(ipcp);
0433 }
0434 up_write(&ids->rwsem);
0435
0436 return err;
0437 }
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447 static void ipc_kht_remove(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
0448 {
0449 if (ipcp->key != IPC_PRIVATE)
0450 WARN_ON_ONCE(rhashtable_remove_fast(&ids->key_ht, &ipcp->khtnode,
0451 ipc_kht_params));
0452 }
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467 static int ipc_search_maxidx(struct ipc_ids *ids, int limit)
0468 {
0469 int tmpidx;
0470 int i;
0471 int retval;
0472
0473 i = ilog2(limit+1);
0474
0475 retval = 0;
0476 for (; i >= 0; i--) {
0477 tmpidx = retval | (1<<i);
0478
0479
0480
0481
0482 tmpidx = tmpidx-1;
0483 if (idr_get_next(&ids->ipcs_idr, &tmpidx))
0484 retval |= (1<<i);
0485 }
0486 return retval - 1;
0487 }
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497 void ipc_rmid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
0498 {
0499 int idx = ipcid_to_idx(ipcp->id);
0500
0501 WARN_ON_ONCE(idr_remove(&ids->ipcs_idr, idx) != ipcp);
0502 ipc_kht_remove(ids, ipcp);
0503 ids->in_use--;
0504 ipcp->deleted = true;
0505
0506 if (unlikely(idx == ids->max_idx)) {
0507 idx = ids->max_idx-1;
0508 if (idx >= 0)
0509 idx = ipc_search_maxidx(ids, idx);
0510 ids->max_idx = idx;
0511 }
0512 }
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522 void ipc_set_key_private(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
0523 {
0524 ipc_kht_remove(ids, ipcp);
0525 ipcp->key = IPC_PRIVATE;
0526 }
0527
0528 bool ipc_rcu_getref(struct kern_ipc_perm *ptr)
0529 {
0530 return refcount_inc_not_zero(&ptr->refcount);
0531 }
0532
0533 void ipc_rcu_putref(struct kern_ipc_perm *ptr,
0534 void (*func)(struct rcu_head *head))
0535 {
0536 if (!refcount_dec_and_test(&ptr->refcount))
0537 return;
0538
0539 call_rcu(&ptr->rcu, func);
0540 }
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553 int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag)
0554 {
0555 kuid_t euid = current_euid();
0556 int requested_mode, granted_mode;
0557
0558 audit_ipc_obj(ipcp);
0559 requested_mode = (flag >> 6) | (flag >> 3) | flag;
0560 granted_mode = ipcp->mode;
0561 if (uid_eq(euid, ipcp->cuid) ||
0562 uid_eq(euid, ipcp->uid))
0563 granted_mode >>= 6;
0564 else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))
0565 granted_mode >>= 3;
0566
0567 if ((requested_mode & ~granted_mode & 0007) &&
0568 !ns_capable(ns->user_ns, CAP_IPC_OWNER))
0569 return -1;
0570
0571 return security_ipc_permission(ipcp, flag);
0572 }
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587 void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out)
0588 {
0589 out->key = in->key;
0590 out->uid = from_kuid_munged(current_user_ns(), in->uid);
0591 out->gid = from_kgid_munged(current_user_ns(), in->gid);
0592 out->cuid = from_kuid_munged(current_user_ns(), in->cuid);
0593 out->cgid = from_kgid_munged(current_user_ns(), in->cgid);
0594 out->mode = in->mode;
0595 out->seq = in->seq;
0596 }
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606 void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out)
0607 {
0608 out->key = in->key;
0609 SET_UID(out->uid, in->uid);
0610 SET_GID(out->gid, in->gid);
0611 SET_UID(out->cuid, in->cuid);
0612 SET_GID(out->cgid, in->cgid);
0613 out->mode = in->mode;
0614 out->seq = in->seq;
0615 }
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627 struct kern_ipc_perm *ipc_obtain_object_idr(struct ipc_ids *ids, int id)
0628 {
0629 struct kern_ipc_perm *out;
0630 int idx = ipcid_to_idx(id);
0631
0632 out = idr_find(&ids->ipcs_idr, idx);
0633 if (!out)
0634 return ERR_PTR(-EINVAL);
0635
0636 return out;
0637 }
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650 struct kern_ipc_perm *ipc_obtain_object_check(struct ipc_ids *ids, int id)
0651 {
0652 struct kern_ipc_perm *out = ipc_obtain_object_idr(ids, id);
0653
0654 if (IS_ERR(out))
0655 goto out;
0656
0657 if (ipc_checkid(out, id))
0658 return ERR_PTR(-EINVAL);
0659 out:
0660 return out;
0661 }
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673 int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
0674 const struct ipc_ops *ops, struct ipc_params *params)
0675 {
0676 if (params->key == IPC_PRIVATE)
0677 return ipcget_new(ns, ids, ops, params);
0678 else
0679 return ipcget_public(ns, ids, ops, params);
0680 }
0681
0682
0683
0684
0685
0686
0687 int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
0688 {
0689 kuid_t uid = make_kuid(current_user_ns(), in->uid);
0690 kgid_t gid = make_kgid(current_user_ns(), in->gid);
0691 if (!uid_valid(uid) || !gid_valid(gid))
0692 return -EINVAL;
0693
0694 out->uid = uid;
0695 out->gid = gid;
0696 out->mode = (out->mode & ~S_IRWXUGO)
0697 | (in->mode & S_IRWXUGO);
0698
0699 return 0;
0700 }
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722 struct kern_ipc_perm *ipcctl_obtain_check(struct ipc_namespace *ns,
0723 struct ipc_ids *ids, int id, int cmd,
0724 struct ipc64_perm *perm, int extra_perm)
0725 {
0726 kuid_t euid;
0727 int err = -EPERM;
0728 struct kern_ipc_perm *ipcp;
0729
0730 ipcp = ipc_obtain_object_check(ids, id);
0731 if (IS_ERR(ipcp)) {
0732 err = PTR_ERR(ipcp);
0733 goto err;
0734 }
0735
0736 audit_ipc_obj(ipcp);
0737 if (cmd == IPC_SET)
0738 audit_ipc_set_perm(extra_perm, perm->uid,
0739 perm->gid, perm->mode);
0740
0741 euid = current_euid();
0742 if (uid_eq(euid, ipcp->cuid) || uid_eq(euid, ipcp->uid) ||
0743 ns_capable(ns->user_ns, CAP_SYS_ADMIN))
0744 return ipcp;
0745 err:
0746 return ERR_PTR(err);
0747 }
0748
0749 #ifdef CONFIG_ARCH_WANT_IPC_PARSE_VERSION
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760 int ipc_parse_version(int *cmd)
0761 {
0762 if (*cmd & IPC_64) {
0763 *cmd ^= IPC_64;
0764 return IPC_64;
0765 } else {
0766 return IPC_OLD;
0767 }
0768 }
0769
0770 #endif
0771
0772 #ifdef CONFIG_PROC_FS
0773 struct ipc_proc_iter {
0774 struct ipc_namespace *ns;
0775 struct pid_namespace *pid_ns;
0776 struct ipc_proc_iface *iface;
0777 };
0778
0779 struct pid_namespace *ipc_seq_pid_ns(struct seq_file *s)
0780 {
0781 struct ipc_proc_iter *iter = s->private;
0782 return iter->pid_ns;
0783 }
0784
0785
0786
0787
0788 static struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t pos,
0789 loff_t *new_pos)
0790 {
0791 struct kern_ipc_perm *ipc = NULL;
0792 int max_idx = ipc_get_maxidx(ids);
0793
0794 if (max_idx == -1 || pos > max_idx)
0795 goto out;
0796
0797 for (; pos <= max_idx; pos++) {
0798 ipc = idr_find(&ids->ipcs_idr, pos);
0799 if (ipc != NULL) {
0800 rcu_read_lock();
0801 ipc_lock_object(ipc);
0802 break;
0803 }
0804 }
0805 out:
0806 *new_pos = pos + 1;
0807 return ipc;
0808 }
0809
0810 static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
0811 {
0812 struct ipc_proc_iter *iter = s->private;
0813 struct ipc_proc_iface *iface = iter->iface;
0814 struct kern_ipc_perm *ipc = it;
0815
0816
0817 if (ipc && ipc != SEQ_START_TOKEN)
0818 ipc_unlock(ipc);
0819
0820 return sysvipc_find_ipc(&iter->ns->ids[iface->ids], *pos, pos);
0821 }
0822
0823
0824
0825
0826
0827 static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
0828 {
0829 struct ipc_proc_iter *iter = s->private;
0830 struct ipc_proc_iface *iface = iter->iface;
0831 struct ipc_ids *ids;
0832
0833 ids = &iter->ns->ids[iface->ids];
0834
0835
0836
0837
0838
0839 down_read(&ids->rwsem);
0840
0841
0842 if (*pos < 0)
0843 return NULL;
0844
0845
0846 if (*pos == 0)
0847 return SEQ_START_TOKEN;
0848
0849
0850 return sysvipc_find_ipc(ids, *pos - 1, pos);
0851 }
0852
0853 static void sysvipc_proc_stop(struct seq_file *s, void *it)
0854 {
0855 struct kern_ipc_perm *ipc = it;
0856 struct ipc_proc_iter *iter = s->private;
0857 struct ipc_proc_iface *iface = iter->iface;
0858 struct ipc_ids *ids;
0859
0860
0861 if (ipc && ipc != SEQ_START_TOKEN)
0862 ipc_unlock(ipc);
0863
0864 ids = &iter->ns->ids[iface->ids];
0865
0866 up_read(&ids->rwsem);
0867 }
0868
0869 static int sysvipc_proc_show(struct seq_file *s, void *it)
0870 {
0871 struct ipc_proc_iter *iter = s->private;
0872 struct ipc_proc_iface *iface = iter->iface;
0873
0874 if (it == SEQ_START_TOKEN) {
0875 seq_puts(s, iface->header);
0876 return 0;
0877 }
0878
0879 return iface->show(s, it);
0880 }
0881
0882 static const struct seq_operations sysvipc_proc_seqops = {
0883 .start = sysvipc_proc_start,
0884 .stop = sysvipc_proc_stop,
0885 .next = sysvipc_proc_next,
0886 .show = sysvipc_proc_show,
0887 };
0888
0889 static int sysvipc_proc_open(struct inode *inode, struct file *file)
0890 {
0891 struct ipc_proc_iter *iter;
0892
0893 iter = __seq_open_private(file, &sysvipc_proc_seqops, sizeof(*iter));
0894 if (!iter)
0895 return -ENOMEM;
0896
0897 iter->iface = pde_data(inode);
0898 iter->ns = get_ipc_ns(current->nsproxy->ipc_ns);
0899 iter->pid_ns = get_pid_ns(task_active_pid_ns(current));
0900
0901 return 0;
0902 }
0903
0904 static int sysvipc_proc_release(struct inode *inode, struct file *file)
0905 {
0906 struct seq_file *seq = file->private_data;
0907 struct ipc_proc_iter *iter = seq->private;
0908 put_ipc_ns(iter->ns);
0909 put_pid_ns(iter->pid_ns);
0910 return seq_release_private(inode, file);
0911 }
0912
0913 static const struct proc_ops sysvipc_proc_ops = {
0914 .proc_flags = PROC_ENTRY_PERMANENT,
0915 .proc_open = sysvipc_proc_open,
0916 .proc_read = seq_read,
0917 .proc_lseek = seq_lseek,
0918 .proc_release = sysvipc_proc_release,
0919 };
0920 #endif