.. | .. |
---|
49 | 49 | #include <linux/syscalls.h> |
---|
50 | 50 | #include <linux/kprobes.h> |
---|
51 | 51 | #include <linux/user_namespace.h> |
---|
| 52 | +#include <linux/time_namespace.h> |
---|
52 | 53 | #include <linux/binfmts.h> |
---|
53 | 54 | |
---|
54 | 55 | #include <linux/sched.h> |
---|
.. | .. |
---|
74 | 75 | #include <asm/unistd.h> |
---|
75 | 76 | |
---|
76 | 77 | #include "uid16.h" |
---|
| 78 | + |
---|
| 79 | +#include <trace/hooks/sys.h> |
---|
77 | 80 | |
---|
78 | 81 | #ifndef SET_UNALIGN_CTL |
---|
79 | 82 | # define SET_UNALIGN_CTL(a, b) (-EINVAL) |
---|
.. | .. |
---|
105 | 108 | #ifndef SET_TSC_CTL |
---|
106 | 109 | # define SET_TSC_CTL(a) (-EINVAL) |
---|
107 | 110 | #endif |
---|
108 | | -#ifndef MPX_ENABLE_MANAGEMENT |
---|
109 | | -# define MPX_ENABLE_MANAGEMENT() (-EINVAL) |
---|
110 | | -#endif |
---|
111 | | -#ifndef MPX_DISABLE_MANAGEMENT |
---|
112 | | -# define MPX_DISABLE_MANAGEMENT() (-EINVAL) |
---|
113 | | -#endif |
---|
114 | 111 | #ifndef GET_FP_MODE |
---|
115 | 112 | # define GET_FP_MODE(a) (-EINVAL) |
---|
116 | 113 | #endif |
---|
.. | .. |
---|
122 | 119 | #endif |
---|
123 | 120 | #ifndef SVE_GET_VL |
---|
124 | 121 | # define SVE_GET_VL() (-EINVAL) |
---|
| 122 | +#endif |
---|
| 123 | +#ifndef PAC_RESET_KEYS |
---|
| 124 | +# define PAC_RESET_KEYS(a, b) (-EINVAL) |
---|
| 125 | +#endif |
---|
| 126 | +#ifndef PAC_SET_ENABLED_KEYS |
---|
| 127 | +# define PAC_SET_ENABLED_KEYS(a, b, c) (-EINVAL) |
---|
| 128 | +#endif |
---|
| 129 | +#ifndef PAC_GET_ENABLED_KEYS |
---|
| 130 | +# define PAC_GET_ENABLED_KEYS(a) (-EINVAL) |
---|
125 | 131 | #endif |
---|
126 | 132 | #ifndef SET_TAGGED_ADDR_CTRL |
---|
127 | 133 | # define SET_TAGGED_ADDR_CTRL(a) (-EINVAL) |
---|
.. | .. |
---|
377 | 383 | if (rgid != (gid_t) -1) { |
---|
378 | 384 | if (gid_eq(old->gid, krgid) || |
---|
379 | 385 | gid_eq(old->egid, krgid) || |
---|
380 | | - ns_capable(old->user_ns, CAP_SETGID)) |
---|
| 386 | + ns_capable_setid(old->user_ns, CAP_SETGID)) |
---|
381 | 387 | new->gid = krgid; |
---|
382 | 388 | else |
---|
383 | 389 | goto error; |
---|
.. | .. |
---|
386 | 392 | if (gid_eq(old->gid, kegid) || |
---|
387 | 393 | gid_eq(old->egid, kegid) || |
---|
388 | 394 | gid_eq(old->sgid, kegid) || |
---|
389 | | - ns_capable(old->user_ns, CAP_SETGID)) |
---|
| 395 | + ns_capable_setid(old->user_ns, CAP_SETGID)) |
---|
390 | 396 | new->egid = kegid; |
---|
391 | 397 | else |
---|
392 | 398 | goto error; |
---|
.. | .. |
---|
396 | 402 | (egid != (gid_t) -1 && !gid_eq(kegid, old->gid))) |
---|
397 | 403 | new->sgid = new->egid; |
---|
398 | 404 | new->fsgid = new->egid; |
---|
| 405 | + |
---|
| 406 | + retval = security_task_fix_setgid(new, old, LSM_SETID_RE); |
---|
| 407 | + if (retval < 0) |
---|
| 408 | + goto error; |
---|
399 | 409 | |
---|
400 | 410 | return commit_creds(new); |
---|
401 | 411 | |
---|
.. | .. |
---|
432 | 442 | old = current_cred(); |
---|
433 | 443 | |
---|
434 | 444 | retval = -EPERM; |
---|
435 | | - if (ns_capable(old->user_ns, CAP_SETGID)) |
---|
| 445 | + if (ns_capable_setid(old->user_ns, CAP_SETGID)) |
---|
436 | 446 | new->gid = new->egid = new->sgid = new->fsgid = kgid; |
---|
437 | 447 | else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid)) |
---|
438 | 448 | new->egid = new->fsgid = kgid; |
---|
439 | 449 | else |
---|
| 450 | + goto error; |
---|
| 451 | + |
---|
| 452 | + retval = security_task_fix_setgid(new, old, LSM_SETID_ID); |
---|
| 453 | + if (retval < 0) |
---|
440 | 454 | goto error; |
---|
441 | 455 | |
---|
442 | 456 | return commit_creds(new); |
---|
.. | .. |
---|
521 | 535 | new->uid = kruid; |
---|
522 | 536 | if (!uid_eq(old->uid, kruid) && |
---|
523 | 537 | !uid_eq(old->euid, kruid) && |
---|
524 | | - !ns_capable(old->user_ns, CAP_SETUID)) |
---|
| 538 | + !ns_capable_setid(old->user_ns, CAP_SETUID)) |
---|
525 | 539 | goto error; |
---|
526 | 540 | } |
---|
527 | 541 | |
---|
.. | .. |
---|
530 | 544 | if (!uid_eq(old->uid, keuid) && |
---|
531 | 545 | !uid_eq(old->euid, keuid) && |
---|
532 | 546 | !uid_eq(old->suid, keuid) && |
---|
533 | | - !ns_capable(old->user_ns, CAP_SETUID)) |
---|
| 547 | + !ns_capable_setid(old->user_ns, CAP_SETUID)) |
---|
534 | 548 | goto error; |
---|
535 | 549 | } |
---|
536 | 550 | |
---|
.. | .. |
---|
589 | 603 | old = current_cred(); |
---|
590 | 604 | |
---|
591 | 605 | retval = -EPERM; |
---|
592 | | - if (ns_capable(old->user_ns, CAP_SETUID)) { |
---|
| 606 | + if (ns_capable_setid(old->user_ns, CAP_SETUID)) { |
---|
593 | 607 | new->suid = new->uid = kuid; |
---|
594 | 608 | if (!uid_eq(kuid, old->uid)) { |
---|
595 | 609 | retval = set_user(new); |
---|
.. | .. |
---|
630 | 644 | struct cred *new; |
---|
631 | 645 | int retval; |
---|
632 | 646 | kuid_t kruid, keuid, ksuid; |
---|
| 647 | + bool ruid_new, euid_new, suid_new; |
---|
633 | 648 | |
---|
634 | 649 | kruid = make_kuid(ns, ruid); |
---|
635 | 650 | keuid = make_kuid(ns, euid); |
---|
.. | .. |
---|
644 | 659 | if ((suid != (uid_t) -1) && !uid_valid(ksuid)) |
---|
645 | 660 | return -EINVAL; |
---|
646 | 661 | |
---|
| 662 | + old = current_cred(); |
---|
| 663 | + |
---|
| 664 | + /* check for no-op */ |
---|
| 665 | + if ((ruid == (uid_t) -1 || uid_eq(kruid, old->uid)) && |
---|
| 666 | + (euid == (uid_t) -1 || (uid_eq(keuid, old->euid) && |
---|
| 667 | + uid_eq(keuid, old->fsuid))) && |
---|
| 668 | + (suid == (uid_t) -1 || uid_eq(ksuid, old->suid))) |
---|
| 669 | + return 0; |
---|
| 670 | + |
---|
| 671 | + ruid_new = ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) && |
---|
| 672 | + !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid); |
---|
| 673 | + euid_new = euid != (uid_t) -1 && !uid_eq(keuid, old->uid) && |
---|
| 674 | + !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid); |
---|
| 675 | + suid_new = suid != (uid_t) -1 && !uid_eq(ksuid, old->uid) && |
---|
| 676 | + !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid); |
---|
| 677 | + if ((ruid_new || euid_new || suid_new) && |
---|
| 678 | + !ns_capable_setid(old->user_ns, CAP_SETUID)) |
---|
| 679 | + return -EPERM; |
---|
| 680 | + |
---|
647 | 681 | new = prepare_creds(); |
---|
648 | 682 | if (!new) |
---|
649 | 683 | return -ENOMEM; |
---|
650 | | - |
---|
651 | | - old = current_cred(); |
---|
652 | | - |
---|
653 | | - retval = -EPERM; |
---|
654 | | - if (!ns_capable(old->user_ns, CAP_SETUID)) { |
---|
655 | | - if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) && |
---|
656 | | - !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid)) |
---|
657 | | - goto error; |
---|
658 | | - if (euid != (uid_t) -1 && !uid_eq(keuid, old->uid) && |
---|
659 | | - !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid)) |
---|
660 | | - goto error; |
---|
661 | | - if (suid != (uid_t) -1 && !uid_eq(ksuid, old->uid) && |
---|
662 | | - !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid)) |
---|
663 | | - goto error; |
---|
664 | | - } |
---|
665 | 684 | |
---|
666 | 685 | if (ruid != (uid_t) -1) { |
---|
667 | 686 | new->uid = kruid; |
---|
.. | .. |
---|
722 | 741 | struct cred *new; |
---|
723 | 742 | int retval; |
---|
724 | 743 | kgid_t krgid, kegid, ksgid; |
---|
| 744 | + bool rgid_new, egid_new, sgid_new; |
---|
725 | 745 | |
---|
726 | 746 | krgid = make_kgid(ns, rgid); |
---|
727 | 747 | kegid = make_kgid(ns, egid); |
---|
.. | .. |
---|
734 | 754 | if ((sgid != (gid_t) -1) && !gid_valid(ksgid)) |
---|
735 | 755 | return -EINVAL; |
---|
736 | 756 | |
---|
| 757 | + old = current_cred(); |
---|
| 758 | + |
---|
| 759 | + /* check for no-op */ |
---|
| 760 | + if ((rgid == (gid_t) -1 || gid_eq(krgid, old->gid)) && |
---|
| 761 | + (egid == (gid_t) -1 || (gid_eq(kegid, old->egid) && |
---|
| 762 | + gid_eq(kegid, old->fsgid))) && |
---|
| 763 | + (sgid == (gid_t) -1 || gid_eq(ksgid, old->sgid))) |
---|
| 764 | + return 0; |
---|
| 765 | + |
---|
| 766 | + rgid_new = rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) && |
---|
| 767 | + !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid); |
---|
| 768 | + egid_new = egid != (gid_t) -1 && !gid_eq(kegid, old->gid) && |
---|
| 769 | + !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid); |
---|
| 770 | + sgid_new = sgid != (gid_t) -1 && !gid_eq(ksgid, old->gid) && |
---|
| 771 | + !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid); |
---|
| 772 | + if ((rgid_new || egid_new || sgid_new) && |
---|
| 773 | + !ns_capable_setid(old->user_ns, CAP_SETGID)) |
---|
| 774 | + return -EPERM; |
---|
| 775 | + |
---|
737 | 776 | new = prepare_creds(); |
---|
738 | 777 | if (!new) |
---|
739 | 778 | return -ENOMEM; |
---|
740 | | - old = current_cred(); |
---|
741 | | - |
---|
742 | | - retval = -EPERM; |
---|
743 | | - if (!ns_capable(old->user_ns, CAP_SETGID)) { |
---|
744 | | - if (rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) && |
---|
745 | | - !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid)) |
---|
746 | | - goto error; |
---|
747 | | - if (egid != (gid_t) -1 && !gid_eq(kegid, old->gid) && |
---|
748 | | - !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid)) |
---|
749 | | - goto error; |
---|
750 | | - if (sgid != (gid_t) -1 && !gid_eq(ksgid, old->gid) && |
---|
751 | | - !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid)) |
---|
752 | | - goto error; |
---|
753 | | - } |
---|
754 | 779 | |
---|
755 | 780 | if (rgid != (gid_t) -1) |
---|
756 | 781 | new->gid = krgid; |
---|
.. | .. |
---|
759 | 784 | if (sgid != (gid_t) -1) |
---|
760 | 785 | new->sgid = ksgid; |
---|
761 | 786 | new->fsgid = new->egid; |
---|
| 787 | + |
---|
| 788 | + retval = security_task_fix_setgid(new, old, LSM_SETID_RES); |
---|
| 789 | + if (retval < 0) |
---|
| 790 | + goto error; |
---|
762 | 791 | |
---|
763 | 792 | return commit_creds(new); |
---|
764 | 793 | |
---|
.. | .. |
---|
819 | 848 | |
---|
820 | 849 | if (uid_eq(kuid, old->uid) || uid_eq(kuid, old->euid) || |
---|
821 | 850 | uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) || |
---|
822 | | - ns_capable(old->user_ns, CAP_SETUID)) { |
---|
| 851 | + ns_capable_setid(old->user_ns, CAP_SETUID)) { |
---|
823 | 852 | if (!uid_eq(kuid, old->fsuid)) { |
---|
824 | 853 | new->fsuid = kuid; |
---|
825 | 854 | if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0) |
---|
.. | .. |
---|
863 | 892 | |
---|
864 | 893 | if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->egid) || |
---|
865 | 894 | gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) || |
---|
866 | | - ns_capable(old->user_ns, CAP_SETGID)) { |
---|
| 895 | + ns_capable_setid(old->user_ns, CAP_SETGID)) { |
---|
867 | 896 | if (!gid_eq(kgid, old->fsgid)) { |
---|
868 | 897 | new->fsgid = kgid; |
---|
869 | | - goto change_okay; |
---|
| 898 | + if (security_task_fix_setgid(new,old,LSM_SETID_FS) == 0) |
---|
| 899 | + goto change_okay; |
---|
870 | 900 | } |
---|
871 | 901 | } |
---|
872 | 902 | |
---|
.. | .. |
---|
1212 | 1242 | /* |
---|
1213 | 1243 | * Work around broken programs that cannot handle "Linux 3.0". |
---|
1214 | 1244 | * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40 |
---|
1215 | | - * And we map 4.x to 2.6.60+x, so 4.0 would be 2.6.60. |
---|
| 1245 | + * And we map 4.x and later versions to 2.6.60+x, so 4.0/5.0/6.0/... would be |
---|
| 1246 | + * 2.6.60. |
---|
1216 | 1247 | */ |
---|
1217 | 1248 | static int override_release(char __user *release, size_t len) |
---|
1218 | 1249 | { |
---|
.. | .. |
---|
1538 | 1569 | |
---|
1539 | 1570 | if (resource >= RLIM_NLIMITS) |
---|
1540 | 1571 | return -EINVAL; |
---|
| 1572 | + resource = array_index_nospec(resource, RLIM_NLIMITS); |
---|
| 1573 | + |
---|
1541 | 1574 | if (new_rlim) { |
---|
1542 | 1575 | if (new_rlim->rlim_cur > new_rlim->rlim_max) |
---|
1543 | 1576 | return -EINVAL; |
---|
.. | .. |
---|
1563 | 1596 | retval = -EPERM; |
---|
1564 | 1597 | if (!retval) |
---|
1565 | 1598 | retval = security_task_setrlimit(tsk, resource, new_rlim); |
---|
1566 | | - if (resource == RLIMIT_CPU && new_rlim->rlim_cur == 0) { |
---|
1567 | | - /* |
---|
1568 | | - * The caller is asking for an immediate RLIMIT_CPU |
---|
1569 | | - * expiry. But we use the zero value to mean "it was |
---|
1570 | | - * never set". So let's cheat and make it one second |
---|
1571 | | - * instead |
---|
1572 | | - */ |
---|
1573 | | - new_rlim->rlim_cur = 1; |
---|
1574 | | - } |
---|
1575 | 1599 | } |
---|
1576 | 1600 | if (!retval) { |
---|
1577 | 1601 | if (old_rlim) |
---|
.. | .. |
---|
1582 | 1606 | task_unlock(tsk->group_leader); |
---|
1583 | 1607 | |
---|
1584 | 1608 | /* |
---|
1585 | | - * RLIMIT_CPU handling. Note that the kernel fails to return an error |
---|
1586 | | - * code if it rejected the user's attempt to set RLIMIT_CPU. This is a |
---|
1587 | | - * very long-standing error, and fixing it now risks breakage of |
---|
1588 | | - * applications, so we live with it |
---|
| 1609 | + * RLIMIT_CPU handling. Arm the posix CPU timer if the limit is not |
---|
| 1610 | + * infite. In case of RLIM_INFINITY the posix CPU timer code |
---|
| 1611 | + * ignores the rlimit. |
---|
1589 | 1612 | */ |
---|
1590 | 1613 | if (!retval && new_rlim && resource == RLIMIT_CPU && |
---|
1591 | 1614 | new_rlim->rlim_cur != RLIM_INFINITY && |
---|
.. | .. |
---|
1753 | 1776 | |
---|
1754 | 1777 | if (who == RUSAGE_CHILDREN) |
---|
1755 | 1778 | break; |
---|
| 1779 | + fallthrough; |
---|
1756 | 1780 | |
---|
1757 | 1781 | case RUSAGE_SELF: |
---|
1758 | 1782 | thread_group_cputime_adjusted(p, &tgutime, &tgstime); |
---|
.. | .. |
---|
1778 | 1802 | unlock_task_sighand(p, &flags); |
---|
1779 | 1803 | |
---|
1780 | 1804 | out: |
---|
1781 | | - r->ru_utime = ns_to_timeval(utime); |
---|
1782 | | - r->ru_stime = ns_to_timeval(stime); |
---|
| 1805 | + r->ru_utime = ns_to_kernel_old_timeval(utime); |
---|
| 1806 | + r->ru_stime = ns_to_kernel_old_timeval(stime); |
---|
1783 | 1807 | |
---|
1784 | 1808 | if (who != RUSAGE_CHILDREN) { |
---|
1785 | 1809 | struct mm_struct *mm = get_task_mm(p); |
---|
.. | .. |
---|
1858 | 1882 | if (exe_file) { |
---|
1859 | 1883 | struct vm_area_struct *vma; |
---|
1860 | 1884 | |
---|
1861 | | - down_read(&mm->mmap_sem); |
---|
| 1885 | + mmap_read_lock(mm); |
---|
1862 | 1886 | for (vma = mm->mmap; vma; vma = vma->vm_next) { |
---|
1863 | 1887 | if (!vma->vm_file) |
---|
1864 | 1888 | continue; |
---|
.. | .. |
---|
1867 | 1891 | goto exit_err; |
---|
1868 | 1892 | } |
---|
1869 | 1893 | |
---|
1870 | | - up_read(&mm->mmap_sem); |
---|
| 1894 | + mmap_read_unlock(mm); |
---|
1871 | 1895 | fput(exe_file); |
---|
1872 | 1896 | } |
---|
1873 | 1897 | |
---|
.. | .. |
---|
1881 | 1905 | fdput(exe); |
---|
1882 | 1906 | return err; |
---|
1883 | 1907 | exit_err: |
---|
1884 | | - up_read(&mm->mmap_sem); |
---|
| 1908 | + mmap_read_unlock(mm); |
---|
1885 | 1909 | fput(exe_file); |
---|
1886 | 1910 | goto exit; |
---|
1887 | 1911 | } |
---|
1888 | 1912 | |
---|
1889 | 1913 | /* |
---|
| 1914 | + * Check arithmetic relations of passed addresses. |
---|
| 1915 | + * |
---|
1890 | 1916 | * WARNING: we don't require any capability here so be very careful |
---|
1891 | 1917 | * in what is allowed for modification from userspace. |
---|
1892 | 1918 | */ |
---|
1893 | | -static int validate_prctl_map(struct prctl_mm_map *prctl_map) |
---|
| 1919 | +static int validate_prctl_map_addr(struct prctl_mm_map *prctl_map) |
---|
1894 | 1920 | { |
---|
1895 | 1921 | unsigned long mmap_max_addr = TASK_SIZE; |
---|
1896 | | - struct mm_struct *mm = current->mm; |
---|
1897 | 1922 | int error = -EINVAL, i; |
---|
1898 | 1923 | |
---|
1899 | 1924 | static const unsigned char offsets[] = { |
---|
.. | .. |
---|
1947 | 1972 | prctl_map->start_data)) |
---|
1948 | 1973 | goto out; |
---|
1949 | 1974 | |
---|
1950 | | - /* |
---|
1951 | | - * Someone is trying to cheat the auxv vector. |
---|
1952 | | - */ |
---|
1953 | | - if (prctl_map->auxv_size) { |
---|
1954 | | - if (!prctl_map->auxv || prctl_map->auxv_size > sizeof(mm->saved_auxv)) |
---|
1955 | | - goto out; |
---|
1956 | | - } |
---|
1957 | | - |
---|
1958 | | - /* |
---|
1959 | | - * Finally, make sure the caller has the rights to |
---|
1960 | | - * change /proc/pid/exe link: only local sys admin should |
---|
1961 | | - * be allowed to. |
---|
1962 | | - */ |
---|
1963 | | - if (prctl_map->exe_fd != (u32)-1) { |
---|
1964 | | - if (!ns_capable(current_user_ns(), CAP_SYS_ADMIN)) |
---|
1965 | | - goto out; |
---|
1966 | | - } |
---|
1967 | | - |
---|
1968 | 1975 | error = 0; |
---|
1969 | 1976 | out: |
---|
1970 | 1977 | return error; |
---|
.. | .. |
---|
1991 | 1998 | if (copy_from_user(&prctl_map, addr, sizeof(prctl_map))) |
---|
1992 | 1999 | return -EFAULT; |
---|
1993 | 2000 | |
---|
1994 | | - error = validate_prctl_map(&prctl_map); |
---|
| 2001 | + error = validate_prctl_map_addr(&prctl_map); |
---|
1995 | 2002 | if (error) |
---|
1996 | 2003 | return error; |
---|
1997 | 2004 | |
---|
1998 | 2005 | if (prctl_map.auxv_size) { |
---|
| 2006 | + /* |
---|
| 2007 | + * Someone is trying to cheat the auxv vector. |
---|
| 2008 | + */ |
---|
| 2009 | + if (!prctl_map.auxv || |
---|
| 2010 | + prctl_map.auxv_size > sizeof(mm->saved_auxv)) |
---|
| 2011 | + return -EINVAL; |
---|
| 2012 | + |
---|
1999 | 2013 | memset(user_auxv, 0, sizeof(user_auxv)); |
---|
2000 | 2014 | if (copy_from_user(user_auxv, |
---|
2001 | 2015 | (const void __user *)prctl_map.auxv, |
---|
.. | .. |
---|
2008 | 2022 | } |
---|
2009 | 2023 | |
---|
2010 | 2024 | if (prctl_map.exe_fd != (u32)-1) { |
---|
| 2025 | + /* |
---|
| 2026 | + * Check if the current user is checkpoint/restore capable. |
---|
| 2027 | + * At the time of this writing, it checks for CAP_SYS_ADMIN |
---|
| 2028 | + * or CAP_CHECKPOINT_RESTORE. |
---|
| 2029 | + * Note that a user with access to ptrace can masquerade an |
---|
| 2030 | + * arbitrary program as any executable, even setuid ones. |
---|
| 2031 | + * This may have implications in the tomoyo subsystem. |
---|
| 2032 | + */ |
---|
| 2033 | + if (!checkpoint_restore_ns_capable(current_user_ns())) |
---|
| 2034 | + return -EPERM; |
---|
| 2035 | + |
---|
2011 | 2036 | error = prctl_set_mm_exe_file(mm, prctl_map.exe_fd); |
---|
2012 | 2037 | if (error) |
---|
2013 | 2038 | return error; |
---|
2014 | 2039 | } |
---|
2015 | 2040 | |
---|
2016 | 2041 | /* |
---|
2017 | | - * arg_lock protects concurent updates but we still need mmap_sem for |
---|
| 2042 | + * arg_lock protects concurent updates but we still need mmap_lock for |
---|
2018 | 2043 | * read to exclude races with sys_brk. |
---|
2019 | 2044 | */ |
---|
2020 | | - down_read(&mm->mmap_sem); |
---|
| 2045 | + mmap_read_lock(mm); |
---|
2021 | 2046 | |
---|
2022 | 2047 | /* |
---|
2023 | 2048 | * We don't validate if these members are pointing to |
---|
.. | .. |
---|
2025 | 2050 | * VMAs already unmapped and kernel uses these members for statistics |
---|
2026 | 2051 | * output in procfs mostly, except |
---|
2027 | 2052 | * |
---|
2028 | | - * - @start_brk/@brk which are used in do_brk but kernel lookups |
---|
| 2053 | + * - @start_brk/@brk which are used in do_brk_flags but kernel lookups |
---|
2029 | 2054 | * for VMAs when updating these memvers so anything wrong written |
---|
2030 | 2055 | * here cause kernel to swear at userspace program but won't lead |
---|
2031 | 2056 | * to any problem in kernel itself |
---|
.. | .. |
---|
2056 | 2081 | if (prctl_map.auxv_size) |
---|
2057 | 2082 | memcpy(mm->saved_auxv, user_auxv, sizeof(user_auxv)); |
---|
2058 | 2083 | |
---|
2059 | | - up_read(&mm->mmap_sem); |
---|
| 2084 | + mmap_read_unlock(mm); |
---|
2060 | 2085 | return 0; |
---|
2061 | 2086 | } |
---|
2062 | 2087 | #endif /* CONFIG_CHECKPOINT_RESTORE */ |
---|
.. | .. |
---|
2095 | 2120 | unsigned long arg4, unsigned long arg5) |
---|
2096 | 2121 | { |
---|
2097 | 2122 | struct mm_struct *mm = current->mm; |
---|
2098 | | - struct prctl_mm_map prctl_map; |
---|
| 2123 | + struct prctl_mm_map prctl_map = { |
---|
| 2124 | + .auxv = NULL, |
---|
| 2125 | + .auxv_size = 0, |
---|
| 2126 | + .exe_fd = -1, |
---|
| 2127 | + }; |
---|
2099 | 2128 | struct vm_area_struct *vma; |
---|
2100 | 2129 | int error; |
---|
2101 | 2130 | |
---|
.. | .. |
---|
2123 | 2152 | |
---|
2124 | 2153 | error = -EINVAL; |
---|
2125 | 2154 | |
---|
2126 | | - down_write(&mm->mmap_sem); |
---|
| 2155 | + /* |
---|
| 2156 | + * arg_lock protects concurent updates of arg boundaries, we need |
---|
| 2157 | + * mmap_lock for a) concurrent sys_brk, b) finding VMA for addr |
---|
| 2158 | + * validation. |
---|
| 2159 | + */ |
---|
| 2160 | + mmap_read_lock(mm); |
---|
2127 | 2161 | vma = find_vma(mm, addr); |
---|
2128 | 2162 | |
---|
| 2163 | + spin_lock(&mm->arg_lock); |
---|
2129 | 2164 | prctl_map.start_code = mm->start_code; |
---|
2130 | 2165 | prctl_map.end_code = mm->end_code; |
---|
2131 | 2166 | prctl_map.start_data = mm->start_data; |
---|
.. | .. |
---|
2137 | 2172 | prctl_map.arg_end = mm->arg_end; |
---|
2138 | 2173 | prctl_map.env_start = mm->env_start; |
---|
2139 | 2174 | prctl_map.env_end = mm->env_end; |
---|
2140 | | - prctl_map.auxv = NULL; |
---|
2141 | | - prctl_map.auxv_size = 0; |
---|
2142 | | - prctl_map.exe_fd = -1; |
---|
2143 | 2175 | |
---|
2144 | 2176 | switch (opt) { |
---|
2145 | 2177 | case PR_SET_MM_START_CODE: |
---|
.. | .. |
---|
2179 | 2211 | goto out; |
---|
2180 | 2212 | } |
---|
2181 | 2213 | |
---|
2182 | | - error = validate_prctl_map(&prctl_map); |
---|
| 2214 | + error = validate_prctl_map_addr(&prctl_map); |
---|
2183 | 2215 | if (error) |
---|
2184 | 2216 | goto out; |
---|
2185 | 2217 | |
---|
.. | .. |
---|
2216 | 2248 | |
---|
2217 | 2249 | error = 0; |
---|
2218 | 2250 | out: |
---|
2219 | | - up_write(&mm->mmap_sem); |
---|
| 2251 | + spin_unlock(&mm->arg_lock); |
---|
| 2252 | + mmap_read_unlock(mm); |
---|
2220 | 2253 | return error; |
---|
2221 | 2254 | } |
---|
2222 | 2255 | |
---|
2223 | 2256 | #ifdef CONFIG_CHECKPOINT_RESTORE |
---|
2224 | | -static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr) |
---|
| 2257 | +static int prctl_get_tid_address(struct task_struct *me, int __user * __user *tid_addr) |
---|
2225 | 2258 | { |
---|
2226 | 2259 | return put_user(me->clear_child_tid, tid_addr); |
---|
2227 | 2260 | } |
---|
2228 | 2261 | #else |
---|
2229 | | -static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr) |
---|
| 2262 | +static int prctl_get_tid_address(struct task_struct *me, int __user * __user *tid_addr) |
---|
2230 | 2263 | { |
---|
2231 | 2264 | return -EINVAL; |
---|
2232 | 2265 | } |
---|
.. | .. |
---|
2358 | 2391 | return error; |
---|
2359 | 2392 | if (prev) |
---|
2360 | 2393 | vma = prev->vm_next; |
---|
2361 | | - else /* madvise_remove dropped mmap_sem */ |
---|
| 2394 | + else /* madvise_remove dropped mmap_lock */ |
---|
2362 | 2395 | vma = find_vma(current->mm, start); |
---|
2363 | 2396 | } |
---|
2364 | 2397 | } |
---|
.. | .. |
---|
2386 | 2419 | if (end == start) |
---|
2387 | 2420 | return 0; |
---|
2388 | 2421 | |
---|
2389 | | - down_write(&mm->mmap_sem); |
---|
| 2422 | + mmap_write_lock(mm); |
---|
2390 | 2423 | |
---|
2391 | 2424 | switch (opt) { |
---|
2392 | 2425 | case PR_SET_VMA_ANON_NAME: |
---|
.. | .. |
---|
2396 | 2429 | error = -EINVAL; |
---|
2397 | 2430 | } |
---|
2398 | 2431 | |
---|
2399 | | - up_write(&mm->mmap_sem); |
---|
| 2432 | + mmap_write_unlock(mm); |
---|
2400 | 2433 | |
---|
2401 | 2434 | return error; |
---|
2402 | 2435 | } |
---|
.. | .. |
---|
2407 | 2440 | return -EINVAL; |
---|
2408 | 2441 | } |
---|
2409 | 2442 | #endif |
---|
| 2443 | + |
---|
| 2444 | +#define PR_IO_FLUSHER (PF_MEMALLOC_NOIO | PF_LOCAL_THROTTLE) |
---|
2410 | 2445 | |
---|
2411 | 2446 | SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, |
---|
2412 | 2447 | unsigned long, arg4, unsigned long, arg5) |
---|
.. | .. |
---|
2555 | 2590 | error = prctl_set_mm(arg2, arg3, arg4, arg5); |
---|
2556 | 2591 | break; |
---|
2557 | 2592 | case PR_GET_TID_ADDRESS: |
---|
2558 | | - error = prctl_get_tid_address(me, (int __user **)arg2); |
---|
| 2593 | + error = prctl_get_tid_address(me, (int __user * __user *)arg2); |
---|
2559 | 2594 | break; |
---|
2560 | 2595 | case PR_SET_CHILD_SUBREAPER: |
---|
2561 | 2596 | me->signal->is_child_subreaper = !!arg2; |
---|
.. | .. |
---|
2586 | 2621 | case PR_SET_THP_DISABLE: |
---|
2587 | 2622 | if (arg3 || arg4 || arg5) |
---|
2588 | 2623 | return -EINVAL; |
---|
2589 | | - if (down_write_killable(&me->mm->mmap_sem)) |
---|
| 2624 | + if (mmap_write_lock_killable(me->mm)) |
---|
2590 | 2625 | return -EINTR; |
---|
2591 | 2626 | if (arg2) |
---|
2592 | 2627 | set_bit(MMF_DISABLE_THP, &me->mm->flags); |
---|
2593 | 2628 | else |
---|
2594 | 2629 | clear_bit(MMF_DISABLE_THP, &me->mm->flags); |
---|
2595 | | - up_write(&me->mm->mmap_sem); |
---|
| 2630 | + mmap_write_unlock(me->mm); |
---|
2596 | 2631 | break; |
---|
2597 | 2632 | case PR_MPX_ENABLE_MANAGEMENT: |
---|
2598 | | - if (arg2 || arg3 || arg4 || arg5) |
---|
2599 | | - return -EINVAL; |
---|
2600 | | - error = MPX_ENABLE_MANAGEMENT(); |
---|
2601 | | - break; |
---|
2602 | 2633 | case PR_MPX_DISABLE_MANAGEMENT: |
---|
2603 | | - if (arg2 || arg3 || arg4 || arg5) |
---|
2604 | | - return -EINVAL; |
---|
2605 | | - error = MPX_DISABLE_MANAGEMENT(); |
---|
2606 | | - break; |
---|
| 2634 | + /* No longer implemented: */ |
---|
| 2635 | + return -EINVAL; |
---|
2607 | 2636 | case PR_SET_FP_MODE: |
---|
2608 | 2637 | error = SET_FP_MODE(me, arg2); |
---|
2609 | 2638 | break; |
---|
.. | .. |
---|
2629 | 2658 | case PR_SET_VMA: |
---|
2630 | 2659 | error = prctl_set_vma(arg2, arg3, arg4, arg5); |
---|
2631 | 2660 | break; |
---|
| 2661 | + case PR_PAC_RESET_KEYS: |
---|
| 2662 | + if (arg3 || arg4 || arg5) |
---|
| 2663 | + return -EINVAL; |
---|
| 2664 | + error = PAC_RESET_KEYS(me, arg2); |
---|
| 2665 | + break; |
---|
| 2666 | + case PR_PAC_SET_ENABLED_KEYS: |
---|
| 2667 | + if (arg4 || arg5) |
---|
| 2668 | + return -EINVAL; |
---|
| 2669 | + error = PAC_SET_ENABLED_KEYS(me, arg2, arg3); |
---|
| 2670 | + break; |
---|
| 2671 | + case PR_PAC_GET_ENABLED_KEYS: |
---|
| 2672 | + if (arg2 || arg3 || arg4 || arg5) |
---|
| 2673 | + return -EINVAL; |
---|
| 2674 | + error = PAC_GET_ENABLED_KEYS(me); |
---|
| 2675 | + break; |
---|
2632 | 2676 | case PR_SET_TAGGED_ADDR_CTRL: |
---|
2633 | 2677 | if (arg3 || arg4 || arg5) |
---|
2634 | 2678 | return -EINVAL; |
---|
.. | .. |
---|
2639 | 2683 | return -EINVAL; |
---|
2640 | 2684 | error = GET_TAGGED_ADDR_CTRL(); |
---|
2641 | 2685 | break; |
---|
| 2686 | + case PR_SET_IO_FLUSHER: |
---|
| 2687 | + if (!capable(CAP_SYS_RESOURCE)) |
---|
| 2688 | + return -EPERM; |
---|
| 2689 | + |
---|
| 2690 | + if (arg3 || arg4 || arg5) |
---|
| 2691 | + return -EINVAL; |
---|
| 2692 | + |
---|
| 2693 | + if (arg2 == 1) |
---|
| 2694 | + current->flags |= PR_IO_FLUSHER; |
---|
| 2695 | + else if (!arg2) |
---|
| 2696 | + current->flags &= ~PR_IO_FLUSHER; |
---|
| 2697 | + else |
---|
| 2698 | + return -EINVAL; |
---|
| 2699 | + break; |
---|
| 2700 | + case PR_GET_IO_FLUSHER: |
---|
| 2701 | + if (!capable(CAP_SYS_RESOURCE)) |
---|
| 2702 | + return -EPERM; |
---|
| 2703 | + |
---|
| 2704 | + if (arg2 || arg3 || arg4 || arg5) |
---|
| 2705 | + return -EINVAL; |
---|
| 2706 | + |
---|
| 2707 | + error = (current->flags & PR_IO_FLUSHER) == PR_IO_FLUSHER; |
---|
| 2708 | + break; |
---|
2642 | 2709 | default: |
---|
2643 | 2710 | error = -EINVAL; |
---|
2644 | 2711 | break; |
---|
2645 | 2712 | } |
---|
| 2713 | + trace_android_vh_syscall_prctl_finished(option, me); |
---|
2646 | 2714 | return error; |
---|
2647 | 2715 | } |
---|
2648 | 2716 | |
---|
.. | .. |
---|
2672 | 2740 | memset(info, 0, sizeof(struct sysinfo)); |
---|
2673 | 2741 | |
---|
2674 | 2742 | ktime_get_boottime_ts64(&tp); |
---|
| 2743 | + timens_add_boottime(&tp); |
---|
2675 | 2744 | info->uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0); |
---|
2676 | 2745 | |
---|
2677 | 2746 | get_avenrun(info->loads, 0, SI_LOAD_SHIFT - FSHIFT); |
---|
.. | .. |
---|
2758 | 2827 | COMPAT_SYSCALL_DEFINE1(sysinfo, struct compat_sysinfo __user *, info) |
---|
2759 | 2828 | { |
---|
2760 | 2829 | struct sysinfo s; |
---|
| 2830 | + struct compat_sysinfo s_32; |
---|
2761 | 2831 | |
---|
2762 | 2832 | do_sysinfo(&s); |
---|
2763 | 2833 | |
---|
.. | .. |
---|
2782 | 2852 | s.freehigh >>= bitcount; |
---|
2783 | 2853 | } |
---|
2784 | 2854 | |
---|
2785 | | - if (!access_ok(VERIFY_WRITE, info, sizeof(struct compat_sysinfo)) || |
---|
2786 | | - __put_user(s.uptime, &info->uptime) || |
---|
2787 | | - __put_user(s.loads[0], &info->loads[0]) || |
---|
2788 | | - __put_user(s.loads[1], &info->loads[1]) || |
---|
2789 | | - __put_user(s.loads[2], &info->loads[2]) || |
---|
2790 | | - __put_user(s.totalram, &info->totalram) || |
---|
2791 | | - __put_user(s.freeram, &info->freeram) || |
---|
2792 | | - __put_user(s.sharedram, &info->sharedram) || |
---|
2793 | | - __put_user(s.bufferram, &info->bufferram) || |
---|
2794 | | - __put_user(s.totalswap, &info->totalswap) || |
---|
2795 | | - __put_user(s.freeswap, &info->freeswap) || |
---|
2796 | | - __put_user(s.procs, &info->procs) || |
---|
2797 | | - __put_user(s.totalhigh, &info->totalhigh) || |
---|
2798 | | - __put_user(s.freehigh, &info->freehigh) || |
---|
2799 | | - __put_user(s.mem_unit, &info->mem_unit)) |
---|
| 2855 | + memset(&s_32, 0, sizeof(s_32)); |
---|
| 2856 | + s_32.uptime = s.uptime; |
---|
| 2857 | + s_32.loads[0] = s.loads[0]; |
---|
| 2858 | + s_32.loads[1] = s.loads[1]; |
---|
| 2859 | + s_32.loads[2] = s.loads[2]; |
---|
| 2860 | + s_32.totalram = s.totalram; |
---|
| 2861 | + s_32.freeram = s.freeram; |
---|
| 2862 | + s_32.sharedram = s.sharedram; |
---|
| 2863 | + s_32.bufferram = s.bufferram; |
---|
| 2864 | + s_32.totalswap = s.totalswap; |
---|
| 2865 | + s_32.freeswap = s.freeswap; |
---|
| 2866 | + s_32.procs = s.procs; |
---|
| 2867 | + s_32.totalhigh = s.totalhigh; |
---|
| 2868 | + s_32.freehigh = s.freehigh; |
---|
| 2869 | + s_32.mem_unit = s.mem_unit; |
---|
| 2870 | + if (copy_to_user(info, &s_32, sizeof(s_32))) |
---|
2800 | 2871 | return -EFAULT; |
---|
2801 | | - |
---|
2802 | 2872 | return 0; |
---|
2803 | 2873 | } |
---|
2804 | 2874 | #endif /* CONFIG_COMPAT */ |
---|