| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* Userspace key control operations |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. |
|---|
| 4 | 5 | * Written by David Howells (dhowells@redhat.com) |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or |
|---|
| 7 | | - * modify it under the terms of the GNU General Public License |
|---|
| 8 | | - * as published by the Free Software Foundation; either version |
|---|
| 9 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 10 | 6 | */ |
|---|
| 11 | 7 | |
|---|
| 12 | | -#include <linux/module.h> |
|---|
| 13 | 8 | #include <linux/init.h> |
|---|
| 14 | 9 | #include <linux/sched.h> |
|---|
| 15 | 10 | #include <linux/sched/task.h> |
|---|
| .. | .. |
|---|
| 30 | 25 | #include "internal.h" |
|---|
| 31 | 26 | |
|---|
| 32 | 27 | #define KEY_MAX_DESC_SIZE 4096 |
|---|
| 28 | + |
|---|
| 29 | +static const unsigned char keyrings_capabilities[2] = { |
|---|
| 30 | + [0] = (KEYCTL_CAPS0_CAPABILITIES | |
|---|
| 31 | + (IS_ENABLED(CONFIG_PERSISTENT_KEYRINGS) ? KEYCTL_CAPS0_PERSISTENT_KEYRINGS : 0) | |
|---|
| 32 | + (IS_ENABLED(CONFIG_KEY_DH_OPERATIONS) ? KEYCTL_CAPS0_DIFFIE_HELLMAN : 0) | |
|---|
| 33 | + (IS_ENABLED(CONFIG_ASYMMETRIC_KEY_TYPE) ? KEYCTL_CAPS0_PUBLIC_KEY : 0) | |
|---|
| 34 | + (IS_ENABLED(CONFIG_BIG_KEYS) ? KEYCTL_CAPS0_BIG_KEY : 0) | |
|---|
| 35 | + KEYCTL_CAPS0_INVALIDATE | |
|---|
| 36 | + KEYCTL_CAPS0_RESTRICT_KEYRING | |
|---|
| 37 | + KEYCTL_CAPS0_MOVE |
|---|
| 38 | + ), |
|---|
| 39 | + [1] = (KEYCTL_CAPS1_NS_KEYRING_NAME | |
|---|
| 40 | + KEYCTL_CAPS1_NS_KEY_TAG | |
|---|
| 41 | + (IS_ENABLED(CONFIG_KEY_NOTIFICATIONS) ? KEYCTL_CAPS1_NOTIFICATIONS : 0) |
|---|
| 42 | + ), |
|---|
| 43 | +}; |
|---|
| 33 | 44 | |
|---|
| 34 | 45 | static int key_get_type_from_user(char *type, |
|---|
| 35 | 46 | const char __user *_type, |
|---|
| .. | .. |
|---|
| 208 | 219 | } |
|---|
| 209 | 220 | |
|---|
| 210 | 221 | /* do the search */ |
|---|
| 211 | | - key = request_key_and_link(ktype, description, callout_info, |
|---|
| 222 | + key = request_key_and_link(ktype, description, NULL, callout_info, |
|---|
| 212 | 223 | callout_len, NULL, key_ref_to_ptr(dest_ref), |
|---|
| 213 | 224 | KEY_ALLOC_IN_QUOTA); |
|---|
| 214 | 225 | if (IS_ERR(key)) { |
|---|
| .. | .. |
|---|
| 420 | 431 | |
|---|
| 421 | 432 | /* Root is permitted to invalidate certain special keys */ |
|---|
| 422 | 433 | if (capable(CAP_SYS_ADMIN)) { |
|---|
| 423 | | - key_ref = lookup_user_key(id, 0, 0); |
|---|
| 434 | + key_ref = lookup_user_key(id, 0, KEY_SYSADMIN_OVERRIDE); |
|---|
| 424 | 435 | if (IS_ERR(key_ref)) |
|---|
| 425 | 436 | goto error; |
|---|
| 426 | 437 | if (test_bit(KEY_FLAG_ROOT_CAN_INVAL, |
|---|
| .. | .. |
|---|
| 465 | 476 | |
|---|
| 466 | 477 | /* Root is permitted to invalidate certain special keyrings */ |
|---|
| 467 | 478 | if (capable(CAP_SYS_ADMIN)) { |
|---|
| 468 | | - keyring_ref = lookup_user_key(ringid, 0, 0); |
|---|
| 479 | + keyring_ref = lookup_user_key(ringid, 0, |
|---|
| 480 | + KEY_SYSADMIN_OVERRIDE); |
|---|
| 469 | 481 | if (IS_ERR(keyring_ref)) |
|---|
| 470 | 482 | goto error; |
|---|
| 471 | 483 | if (test_bit(KEY_FLAG_ROOT_CAN_CLEAR, |
|---|
| .. | .. |
|---|
| 549 | 561 | goto error; |
|---|
| 550 | 562 | } |
|---|
| 551 | 563 | |
|---|
| 552 | | - key_ref = lookup_user_key(id, KEY_LOOKUP_FOR_UNLINK, 0); |
|---|
| 564 | + key_ref = lookup_user_key(id, KEY_LOOKUP_PARTIAL, KEY_NEED_UNLINK); |
|---|
| 553 | 565 | if (IS_ERR(key_ref)) { |
|---|
| 554 | 566 | ret = PTR_ERR(key_ref); |
|---|
| 555 | 567 | goto error2; |
|---|
| .. | .. |
|---|
| 567 | 579 | error2: |
|---|
| 568 | 580 | key_ref_put(keyring_ref); |
|---|
| 569 | 581 | error: |
|---|
| 582 | + return ret; |
|---|
| 583 | +} |
|---|
| 584 | + |
|---|
| 585 | +/* |
|---|
| 586 | + * Move a link to a key from one keyring to another, displacing any matching |
|---|
| 587 | + * key from the destination keyring. |
|---|
| 588 | + * |
|---|
| 589 | + * The key must grant the caller Link permission and both keyrings must grant |
|---|
| 590 | + * the caller Write permission. There must also be a link in the from keyring |
|---|
| 591 | + * to the key. If both keyrings are the same, nothing is done. |
|---|
| 592 | + * |
|---|
| 593 | + * If successful, 0 will be returned. |
|---|
| 594 | + */ |
|---|
| 595 | +long keyctl_keyring_move(key_serial_t id, key_serial_t from_ringid, |
|---|
| 596 | + key_serial_t to_ringid, unsigned int flags) |
|---|
| 597 | +{ |
|---|
| 598 | + key_ref_t key_ref, from_ref, to_ref; |
|---|
| 599 | + long ret; |
|---|
| 600 | + |
|---|
| 601 | + if (flags & ~KEYCTL_MOVE_EXCL) |
|---|
| 602 | + return -EINVAL; |
|---|
| 603 | + |
|---|
| 604 | + key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE, KEY_NEED_LINK); |
|---|
| 605 | + if (IS_ERR(key_ref)) |
|---|
| 606 | + return PTR_ERR(key_ref); |
|---|
| 607 | + |
|---|
| 608 | + from_ref = lookup_user_key(from_ringid, 0, KEY_NEED_WRITE); |
|---|
| 609 | + if (IS_ERR(from_ref)) { |
|---|
| 610 | + ret = PTR_ERR(from_ref); |
|---|
| 611 | + goto error2; |
|---|
| 612 | + } |
|---|
| 613 | + |
|---|
| 614 | + to_ref = lookup_user_key(to_ringid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE); |
|---|
| 615 | + if (IS_ERR(to_ref)) { |
|---|
| 616 | + ret = PTR_ERR(to_ref); |
|---|
| 617 | + goto error3; |
|---|
| 618 | + } |
|---|
| 619 | + |
|---|
| 620 | + ret = key_move(key_ref_to_ptr(key_ref), key_ref_to_ptr(from_ref), |
|---|
| 621 | + key_ref_to_ptr(to_ref), flags); |
|---|
| 622 | + |
|---|
| 623 | + key_ref_put(to_ref); |
|---|
| 624 | +error3: |
|---|
| 625 | + key_ref_put(from_ref); |
|---|
| 626 | +error2: |
|---|
| 627 | + key_ref_put(key_ref); |
|---|
| 570 | 628 | return ret; |
|---|
| 571 | 629 | } |
|---|
| 572 | 630 | |
|---|
| .. | .. |
|---|
| 603 | 661 | key_put(instkey); |
|---|
| 604 | 662 | key_ref = lookup_user_key(keyid, |
|---|
| 605 | 663 | KEY_LOOKUP_PARTIAL, |
|---|
| 606 | | - 0); |
|---|
| 664 | + KEY_AUTHTOKEN_OVERRIDE); |
|---|
| 607 | 665 | if (!IS_ERR(key_ref)) |
|---|
| 608 | 666 | goto okay; |
|---|
| 609 | 667 | } |
|---|
| .. | .. |
|---|
| 702 | 760 | } |
|---|
| 703 | 761 | |
|---|
| 704 | 762 | /* do the search */ |
|---|
| 705 | | - key_ref = keyring_search(keyring_ref, ktype, description); |
|---|
| 763 | + key_ref = keyring_search(keyring_ref, ktype, description, true); |
|---|
| 706 | 764 | if (IS_ERR(key_ref)) { |
|---|
| 707 | 765 | ret = PTR_ERR(key_ref); |
|---|
| 708 | 766 | |
|---|
| .. | .. |
|---|
| 773 | 831 | size_t key_data_len; |
|---|
| 774 | 832 | |
|---|
| 775 | 833 | /* find the key first */ |
|---|
| 776 | | - key_ref = lookup_user_key(keyid, 0, 0); |
|---|
| 834 | + key_ref = lookup_user_key(keyid, 0, KEY_DEFER_PERM_CHECK); |
|---|
| 777 | 835 | if (IS_ERR(key_ref)) { |
|---|
| 778 | 836 | ret = -ENOKEY; |
|---|
| 779 | 837 | goto out; |
|---|
| .. | .. |
|---|
| 820 | 878 | * |
|---|
| 821 | 879 | * Allocating a temporary buffer to hold the keys before |
|---|
| 822 | 880 | * transferring them to user buffer to avoid potential |
|---|
| 823 | | - * deadlock involving page fault and mmap_sem. |
|---|
| 881 | + * deadlock involving page fault and mmap_lock. |
|---|
| 824 | 882 | * |
|---|
| 825 | 883 | * key_data_len = (buflen <= PAGE_SIZE) |
|---|
| 826 | 884 | * ? buflen : actual length of key data |
|---|
| .. | .. |
|---|
| 922 | 980 | ret = -EACCES; |
|---|
| 923 | 981 | down_write(&key->sem); |
|---|
| 924 | 982 | |
|---|
| 925 | | - if (!capable(CAP_SYS_ADMIN)) { |
|---|
| 983 | + { |
|---|
| 984 | + bool is_privileged_op = false; |
|---|
| 985 | + |
|---|
| 926 | 986 | /* only the sysadmin can chown a key to some other UID */ |
|---|
| 927 | 987 | if (user != (uid_t) -1 && !uid_eq(key->uid, uid)) |
|---|
| 928 | | - goto error_put; |
|---|
| 988 | + is_privileged_op = true; |
|---|
| 929 | 989 | |
|---|
| 930 | 990 | /* only the sysadmin can set the key's GID to a group other |
|---|
| 931 | 991 | * than one of those that the current process subscribes to */ |
|---|
| 932 | 992 | if (group != (gid_t) -1 && !gid_eq(gid, key->gid) && !in_group_p(gid)) |
|---|
| 993 | + is_privileged_op = true; |
|---|
| 994 | + |
|---|
| 995 | + if (is_privileged_op && !capable(CAP_SYS_ADMIN)) |
|---|
| 933 | 996 | goto error_put; |
|---|
| 934 | 997 | } |
|---|
| 935 | 998 | |
|---|
| .. | .. |
|---|
| 981 | 1044 | if (group != (gid_t) -1) |
|---|
| 982 | 1045 | key->gid = gid; |
|---|
| 983 | 1046 | |
|---|
| 1047 | + notify_key(key, NOTIFY_KEY_SETATTR, 0); |
|---|
| 984 | 1048 | ret = 0; |
|---|
| 985 | 1049 | |
|---|
| 986 | 1050 | error_put: |
|---|
| .. | .. |
|---|
| 1029 | 1093 | down_write(&key->sem); |
|---|
| 1030 | 1094 | |
|---|
| 1031 | 1095 | /* if we're not the sysadmin, we can only change a key that we own */ |
|---|
| 1032 | | - if (capable(CAP_SYS_ADMIN) || uid_eq(key->uid, current_fsuid())) { |
|---|
| 1096 | + if (uid_eq(key->uid, current_fsuid()) || capable(CAP_SYS_ADMIN)) { |
|---|
| 1033 | 1097 | key->perm = perm; |
|---|
| 1098 | + notify_key(key, NOTIFY_KEY_SETATTR, 0); |
|---|
| 1034 | 1099 | ret = 0; |
|---|
| 1035 | 1100 | } |
|---|
| 1036 | 1101 | |
|---|
| .. | .. |
|---|
| 1104 | 1169 | * |
|---|
| 1105 | 1170 | * If successful, 0 will be returned. |
|---|
| 1106 | 1171 | */ |
|---|
| 1107 | | -long keyctl_instantiate_key_common(key_serial_t id, |
|---|
| 1172 | +static long keyctl_instantiate_key_common(key_serial_t id, |
|---|
| 1108 | 1173 | struct iov_iter *from, |
|---|
| 1109 | 1174 | key_serial_t ringid) |
|---|
| 1110 | 1175 | { |
|---|
| .. | .. |
|---|
| 1406 | 1471 | key_put(instkey); |
|---|
| 1407 | 1472 | key_ref = lookup_user_key(id, |
|---|
| 1408 | 1473 | KEY_LOOKUP_PARTIAL, |
|---|
| 1409 | | - 0); |
|---|
| 1474 | + KEY_AUTHTOKEN_OVERRIDE); |
|---|
| 1410 | 1475 | if (!IS_ERR(key_ref)) |
|---|
| 1411 | 1476 | goto okay; |
|---|
| 1412 | 1477 | } |
|---|
| .. | .. |
|---|
| 1419 | 1484 | okay: |
|---|
| 1420 | 1485 | key = key_ref_to_ptr(key_ref); |
|---|
| 1421 | 1486 | ret = 0; |
|---|
| 1422 | | - if (test_bit(KEY_FLAG_KEEP, &key->flags)) |
|---|
| 1487 | + if (test_bit(KEY_FLAG_KEEP, &key->flags)) { |
|---|
| 1423 | 1488 | ret = -EPERM; |
|---|
| 1424 | | - else |
|---|
| 1489 | + } else { |
|---|
| 1425 | 1490 | key_set_timeout(key, timeout); |
|---|
| 1491 | + notify_key(key, NOTIFY_KEY_SETATTR, 0); |
|---|
| 1492 | + } |
|---|
| 1426 | 1493 | key_put(key); |
|---|
| 1427 | 1494 | |
|---|
| 1428 | 1495 | error: |
|---|
| .. | .. |
|---|
| 1512 | 1579 | return PTR_ERR(instkey); |
|---|
| 1513 | 1580 | key_put(instkey); |
|---|
| 1514 | 1581 | |
|---|
| 1515 | | - key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, 0); |
|---|
| 1582 | + key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, |
|---|
| 1583 | + KEY_AUTHTOKEN_OVERRIDE); |
|---|
| 1516 | 1584 | if (IS_ERR(key_ref)) |
|---|
| 1517 | 1585 | return PTR_ERR(key_ref); |
|---|
| 1518 | 1586 | } |
|---|
| .. | .. |
|---|
| 1588 | 1656 | |
|---|
| 1589 | 1657 | ret = -EPERM; |
|---|
| 1590 | 1658 | oldwork = NULL; |
|---|
| 1591 | | - parent = me->real_parent; |
|---|
| 1659 | + parent = rcu_dereference_protected(me->real_parent, |
|---|
| 1660 | + lockdep_is_held(&tasklist_lock)); |
|---|
| 1592 | 1661 | |
|---|
| 1593 | 1662 | /* the parent mustn't be init and mustn't be a kernel thread */ |
|---|
| 1594 | 1663 | if (parent->pid <= 1 || !parent->mm) |
|---|
| .. | .. |
|---|
| 1629 | 1698 | |
|---|
| 1630 | 1699 | /* the replacement session keyring is applied just prior to userspace |
|---|
| 1631 | 1700 | * restarting */ |
|---|
| 1632 | | - ret = task_work_add(parent, newwork, true); |
|---|
| 1701 | + ret = task_work_add(parent, newwork, TWA_RESUME); |
|---|
| 1633 | 1702 | if (!ret) |
|---|
| 1634 | 1703 | newwork = NULL; |
|---|
| 1635 | 1704 | unlock: |
|---|
| .. | .. |
|---|
| 1693 | 1762 | error: |
|---|
| 1694 | 1763 | key_ref_put(key_ref); |
|---|
| 1695 | 1764 | return ret; |
|---|
| 1765 | +} |
|---|
| 1766 | + |
|---|
| 1767 | +#ifdef CONFIG_KEY_NOTIFICATIONS |
|---|
| 1768 | +/* |
|---|
| 1769 | + * Watch for changes to a key. |
|---|
| 1770 | + * |
|---|
| 1771 | + * The caller must have View permission to watch a key or keyring. |
|---|
| 1772 | + */ |
|---|
| 1773 | +long keyctl_watch_key(key_serial_t id, int watch_queue_fd, int watch_id) |
|---|
| 1774 | +{ |
|---|
| 1775 | + struct watch_queue *wqueue; |
|---|
| 1776 | + struct watch_list *wlist = NULL; |
|---|
| 1777 | + struct watch *watch = NULL; |
|---|
| 1778 | + struct key *key; |
|---|
| 1779 | + key_ref_t key_ref; |
|---|
| 1780 | + long ret; |
|---|
| 1781 | + |
|---|
| 1782 | + if (watch_id < -1 || watch_id > 0xff) |
|---|
| 1783 | + return -EINVAL; |
|---|
| 1784 | + |
|---|
| 1785 | + key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE, KEY_NEED_VIEW); |
|---|
| 1786 | + if (IS_ERR(key_ref)) |
|---|
| 1787 | + return PTR_ERR(key_ref); |
|---|
| 1788 | + key = key_ref_to_ptr(key_ref); |
|---|
| 1789 | + |
|---|
| 1790 | + wqueue = get_watch_queue(watch_queue_fd); |
|---|
| 1791 | + if (IS_ERR(wqueue)) { |
|---|
| 1792 | + ret = PTR_ERR(wqueue); |
|---|
| 1793 | + goto err_key; |
|---|
| 1794 | + } |
|---|
| 1795 | + |
|---|
| 1796 | + if (watch_id >= 0) { |
|---|
| 1797 | + ret = -ENOMEM; |
|---|
| 1798 | + if (!key->watchers) { |
|---|
| 1799 | + wlist = kzalloc(sizeof(*wlist), GFP_KERNEL); |
|---|
| 1800 | + if (!wlist) |
|---|
| 1801 | + goto err_wqueue; |
|---|
| 1802 | + init_watch_list(wlist, NULL); |
|---|
| 1803 | + } |
|---|
| 1804 | + |
|---|
| 1805 | + watch = kzalloc(sizeof(*watch), GFP_KERNEL); |
|---|
| 1806 | + if (!watch) |
|---|
| 1807 | + goto err_wlist; |
|---|
| 1808 | + |
|---|
| 1809 | + init_watch(watch, wqueue); |
|---|
| 1810 | + watch->id = key->serial; |
|---|
| 1811 | + watch->info_id = (u32)watch_id << WATCH_INFO_ID__SHIFT; |
|---|
| 1812 | + |
|---|
| 1813 | + ret = security_watch_key(key); |
|---|
| 1814 | + if (ret < 0) |
|---|
| 1815 | + goto err_watch; |
|---|
| 1816 | + |
|---|
| 1817 | + down_write(&key->sem); |
|---|
| 1818 | + if (!key->watchers) { |
|---|
| 1819 | + key->watchers = wlist; |
|---|
| 1820 | + wlist = NULL; |
|---|
| 1821 | + } |
|---|
| 1822 | + |
|---|
| 1823 | + ret = add_watch_to_object(watch, key->watchers); |
|---|
| 1824 | + up_write(&key->sem); |
|---|
| 1825 | + |
|---|
| 1826 | + if (ret == 0) |
|---|
| 1827 | + watch = NULL; |
|---|
| 1828 | + } else { |
|---|
| 1829 | + ret = -EBADSLT; |
|---|
| 1830 | + if (key->watchers) { |
|---|
| 1831 | + down_write(&key->sem); |
|---|
| 1832 | + ret = remove_watch_from_object(key->watchers, |
|---|
| 1833 | + wqueue, key_serial(key), |
|---|
| 1834 | + false); |
|---|
| 1835 | + up_write(&key->sem); |
|---|
| 1836 | + } |
|---|
| 1837 | + } |
|---|
| 1838 | + |
|---|
| 1839 | +err_watch: |
|---|
| 1840 | + kfree(watch); |
|---|
| 1841 | +err_wlist: |
|---|
| 1842 | + kfree(wlist); |
|---|
| 1843 | +err_wqueue: |
|---|
| 1844 | + put_watch_queue(wqueue); |
|---|
| 1845 | +err_key: |
|---|
| 1846 | + key_put(key); |
|---|
| 1847 | + return ret; |
|---|
| 1848 | +} |
|---|
| 1849 | +#endif /* CONFIG_KEY_NOTIFICATIONS */ |
|---|
| 1850 | + |
|---|
| 1851 | +/* |
|---|
| 1852 | + * Get keyrings subsystem capabilities. |
|---|
| 1853 | + */ |
|---|
| 1854 | +long keyctl_capabilities(unsigned char __user *_buffer, size_t buflen) |
|---|
| 1855 | +{ |
|---|
| 1856 | + size_t size = buflen; |
|---|
| 1857 | + |
|---|
| 1858 | + if (size > 0) { |
|---|
| 1859 | + if (size > sizeof(keyrings_capabilities)) |
|---|
| 1860 | + size = sizeof(keyrings_capabilities); |
|---|
| 1861 | + if (copy_to_user(_buffer, keyrings_capabilities, size) != 0) |
|---|
| 1862 | + return -EFAULT; |
|---|
| 1863 | + if (size < buflen && |
|---|
| 1864 | + clear_user(_buffer + size, buflen - size) != 0) |
|---|
| 1865 | + return -EFAULT; |
|---|
| 1866 | + } |
|---|
| 1867 | + |
|---|
| 1868 | + return sizeof(keyrings_capabilities); |
|---|
| 1696 | 1869 | } |
|---|
| 1697 | 1870 | |
|---|
| 1698 | 1871 | /* |
|---|
| .. | .. |
|---|
| 1811 | 1984 | (const char __user *) arg3, |
|---|
| 1812 | 1985 | (const char __user *) arg4); |
|---|
| 1813 | 1986 | |
|---|
| 1987 | + case KEYCTL_PKEY_QUERY: |
|---|
| 1988 | + if (arg3 != 0) |
|---|
| 1989 | + return -EINVAL; |
|---|
| 1990 | + return keyctl_pkey_query((key_serial_t)arg2, |
|---|
| 1991 | + (const char __user *)arg4, |
|---|
| 1992 | + (struct keyctl_pkey_query __user *)arg5); |
|---|
| 1993 | + |
|---|
| 1994 | + case KEYCTL_PKEY_ENCRYPT: |
|---|
| 1995 | + case KEYCTL_PKEY_DECRYPT: |
|---|
| 1996 | + case KEYCTL_PKEY_SIGN: |
|---|
| 1997 | + return keyctl_pkey_e_d_s( |
|---|
| 1998 | + option, |
|---|
| 1999 | + (const struct keyctl_pkey_params __user *)arg2, |
|---|
| 2000 | + (const char __user *)arg3, |
|---|
| 2001 | + (const void __user *)arg4, |
|---|
| 2002 | + (void __user *)arg5); |
|---|
| 2003 | + |
|---|
| 2004 | + case KEYCTL_PKEY_VERIFY: |
|---|
| 2005 | + return keyctl_pkey_verify( |
|---|
| 2006 | + (const struct keyctl_pkey_params __user *)arg2, |
|---|
| 2007 | + (const char __user *)arg3, |
|---|
| 2008 | + (const void __user *)arg4, |
|---|
| 2009 | + (const void __user *)arg5); |
|---|
| 2010 | + |
|---|
| 2011 | + case KEYCTL_MOVE: |
|---|
| 2012 | + return keyctl_keyring_move((key_serial_t)arg2, |
|---|
| 2013 | + (key_serial_t)arg3, |
|---|
| 2014 | + (key_serial_t)arg4, |
|---|
| 2015 | + (unsigned int)arg5); |
|---|
| 2016 | + |
|---|
| 2017 | + case KEYCTL_CAPABILITIES: |
|---|
| 2018 | + return keyctl_capabilities((unsigned char __user *)arg2, (size_t)arg3); |
|---|
| 2019 | + |
|---|
| 2020 | + case KEYCTL_WATCH_KEY: |
|---|
| 2021 | + return keyctl_watch_key((key_serial_t)arg2, (int)arg3, (int)arg4); |
|---|
| 2022 | + |
|---|
| 1814 | 2023 | default: |
|---|
| 1815 | 2024 | return -EOPNOTSUPP; |
|---|
| 1816 | 2025 | } |
|---|