diff options
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r-- | kernel/auditsc.c | 183 |
1 files changed, 42 insertions, 141 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 4b89f7f95d84..84c74d08c62b 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -866,33 +866,10 @@ static inline void audit_free_names(struct audit_context *context) | |||
866 | { | 866 | { |
867 | struct audit_names *n, *next; | 867 | struct audit_names *n, *next; |
868 | 868 | ||
869 | #if AUDIT_DEBUG == 2 | ||
870 | if (context->put_count + context->ino_count != context->name_count) { | ||
871 | int i = 0; | ||
872 | |||
873 | pr_err("%s:%d(:%d): major=%d in_syscall=%d" | ||
874 | " name_count=%d put_count=%d ino_count=%d" | ||
875 | " [NOT freeing]\n", __FILE__, __LINE__, | ||
876 | context->serial, context->major, context->in_syscall, | ||
877 | context->name_count, context->put_count, | ||
878 | context->ino_count); | ||
879 | list_for_each_entry(n, &context->names_list, list) { | ||
880 | pr_err("names[%d] = %p = %s\n", i++, n->name, | ||
881 | n->name->name ?: "(null)"); | ||
882 | } | ||
883 | dump_stack(); | ||
884 | return; | ||
885 | } | ||
886 | #endif | ||
887 | #if AUDIT_DEBUG | ||
888 | context->put_count = 0; | ||
889 | context->ino_count = 0; | ||
890 | #endif | ||
891 | |||
892 | list_for_each_entry_safe(n, next, &context->names_list, list) { | 869 | list_for_each_entry_safe(n, next, &context->names_list, list) { |
893 | list_del(&n->list); | 870 | list_del(&n->list); |
894 | if (n->name && n->name_put) | 871 | if (n->name) |
895 | final_putname(n->name); | 872 | putname(n->name); |
896 | if (n->should_free) | 873 | if (n->should_free) |
897 | kfree(n); | 874 | kfree(n); |
898 | } | 875 | } |
@@ -1711,9 +1688,6 @@ static struct audit_names *audit_alloc_name(struct audit_context *context, | |||
1711 | list_add_tail(&aname->list, &context->names_list); | 1688 | list_add_tail(&aname->list, &context->names_list); |
1712 | 1689 | ||
1713 | context->name_count++; | 1690 | context->name_count++; |
1714 | #if AUDIT_DEBUG | ||
1715 | context->ino_count++; | ||
1716 | #endif | ||
1717 | return aname; | 1691 | return aname; |
1718 | } | 1692 | } |
1719 | 1693 | ||
@@ -1734,8 +1708,10 @@ __audit_reusename(const __user char *uptr) | |||
1734 | list_for_each_entry(n, &context->names_list, list) { | 1708 | list_for_each_entry(n, &context->names_list, list) { |
1735 | if (!n->name) | 1709 | if (!n->name) |
1736 | continue; | 1710 | continue; |
1737 | if (n->name->uptr == uptr) | 1711 | if (n->name->uptr == uptr) { |
1712 | n->name->refcnt++; | ||
1738 | return n->name; | 1713 | return n->name; |
1714 | } | ||
1739 | } | 1715 | } |
1740 | return NULL; | 1716 | return NULL; |
1741 | } | 1717 | } |
@@ -1752,19 +1728,8 @@ void __audit_getname(struct filename *name) | |||
1752 | struct audit_context *context = current->audit_context; | 1728 | struct audit_context *context = current->audit_context; |
1753 | struct audit_names *n; | 1729 | struct audit_names *n; |
1754 | 1730 | ||
1755 | if (!context->in_syscall) { | 1731 | if (!context->in_syscall) |
1756 | #if AUDIT_DEBUG == 2 | ||
1757 | pr_err("%s:%d(:%d): ignoring getname(%p)\n", | ||
1758 | __FILE__, __LINE__, context->serial, name); | ||
1759 | dump_stack(); | ||
1760 | #endif | ||
1761 | return; | 1732 | return; |
1762 | } | ||
1763 | |||
1764 | #if AUDIT_DEBUG | ||
1765 | /* The filename _must_ have a populated ->name */ | ||
1766 | BUG_ON(!name->name); | ||
1767 | #endif | ||
1768 | 1733 | ||
1769 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); | 1734 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); |
1770 | if (!n) | 1735 | if (!n) |
@@ -1772,56 +1737,13 @@ void __audit_getname(struct filename *name) | |||
1772 | 1737 | ||
1773 | n->name = name; | 1738 | n->name = name; |
1774 | n->name_len = AUDIT_NAME_FULL; | 1739 | n->name_len = AUDIT_NAME_FULL; |
1775 | n->name_put = true; | ||
1776 | name->aname = n; | 1740 | name->aname = n; |
1741 | name->refcnt++; | ||
1777 | 1742 | ||
1778 | if (!context->pwd.dentry) | 1743 | if (!context->pwd.dentry) |
1779 | get_fs_pwd(current->fs, &context->pwd); | 1744 | get_fs_pwd(current->fs, &context->pwd); |
1780 | } | 1745 | } |
1781 | 1746 | ||
1782 | /* audit_putname - intercept a putname request | ||
1783 | * @name: name to intercept and delay for putname | ||
1784 | * | ||
1785 | * If we have stored the name from getname in the audit context, | ||
1786 | * then we delay the putname until syscall exit. | ||
1787 | * Called from include/linux/fs.h:putname(). | ||
1788 | */ | ||
1789 | void audit_putname(struct filename *name) | ||
1790 | { | ||
1791 | struct audit_context *context = current->audit_context; | ||
1792 | |||
1793 | BUG_ON(!context); | ||
1794 | if (!name->aname || !context->in_syscall) { | ||
1795 | #if AUDIT_DEBUG == 2 | ||
1796 | pr_err("%s:%d(:%d): final_putname(%p)\n", | ||
1797 | __FILE__, __LINE__, context->serial, name); | ||
1798 | if (context->name_count) { | ||
1799 | struct audit_names *n; | ||
1800 | int i = 0; | ||
1801 | |||
1802 | list_for_each_entry(n, &context->names_list, list) | ||
1803 | pr_err("name[%d] = %p = %s\n", i++, n->name, | ||
1804 | n->name->name ?: "(null)"); | ||
1805 | } | ||
1806 | #endif | ||
1807 | final_putname(name); | ||
1808 | } | ||
1809 | #if AUDIT_DEBUG | ||
1810 | else { | ||
1811 | ++context->put_count; | ||
1812 | if (context->put_count > context->name_count) { | ||
1813 | pr_err("%s:%d(:%d): major=%d in_syscall=%d putname(%p)" | ||
1814 | " name_count=%d put_count=%d\n", | ||
1815 | __FILE__, __LINE__, | ||
1816 | context->serial, context->major, | ||
1817 | context->in_syscall, name->name, | ||
1818 | context->name_count, context->put_count); | ||
1819 | dump_stack(); | ||
1820 | } | ||
1821 | } | ||
1822 | #endif | ||
1823 | } | ||
1824 | |||
1825 | /** | 1747 | /** |
1826 | * __audit_inode - store the inode and device from a lookup | 1748 | * __audit_inode - store the inode and device from a lookup |
1827 | * @name: name being audited | 1749 | * @name: name being audited |
@@ -1842,10 +1764,6 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
1842 | if (!name) | 1764 | if (!name) |
1843 | goto out_alloc; | 1765 | goto out_alloc; |
1844 | 1766 | ||
1845 | #if AUDIT_DEBUG | ||
1846 | /* The struct filename _must_ have a populated ->name */ | ||
1847 | BUG_ON(!name->name); | ||
1848 | #endif | ||
1849 | /* | 1767 | /* |
1850 | * If we have a pointer to an audit_names entry already, then we can | 1768 | * If we have a pointer to an audit_names entry already, then we can |
1851 | * just use it directly if the type is correct. | 1769 | * just use it directly if the type is correct. |
@@ -1863,7 +1781,17 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
1863 | } | 1781 | } |
1864 | 1782 | ||
1865 | list_for_each_entry_reverse(n, &context->names_list, list) { | 1783 | list_for_each_entry_reverse(n, &context->names_list, list) { |
1866 | if (!n->name || strcmp(n->name->name, name->name)) | 1784 | if (n->ino) { |
1785 | /* valid inode number, use that for the comparison */ | ||
1786 | if (n->ino != inode->i_ino || | ||
1787 | n->dev != inode->i_sb->s_dev) | ||
1788 | continue; | ||
1789 | } else if (n->name) { | ||
1790 | /* inode number has not been set, check the name */ | ||
1791 | if (strcmp(n->name->name, name->name)) | ||
1792 | continue; | ||
1793 | } else | ||
1794 | /* no inode and no name (?!) ... this is odd ... */ | ||
1867 | continue; | 1795 | continue; |
1868 | 1796 | ||
1869 | /* match the correct record type */ | 1797 | /* match the correct record type */ |
@@ -1882,44 +1810,11 @@ out_alloc: | |||
1882 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); | 1810 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); |
1883 | if (!n) | 1811 | if (!n) |
1884 | return; | 1812 | return; |
1885 | /* unfortunately, while we may have a path name to record with the | ||
1886 | * inode, we can't always rely on the string lasting until the end of | ||
1887 | * the syscall so we need to create our own copy, it may fail due to | ||
1888 | * memory allocation issues, but we do our best */ | ||
1889 | if (name) { | 1813 | if (name) { |
1890 | /* we can't use getname_kernel() due to size limits */ | 1814 | n->name = name; |
1891 | size_t len = strlen(name->name) + 1; | 1815 | name->refcnt++; |
1892 | struct filename *new = __getname(); | ||
1893 | |||
1894 | if (unlikely(!new)) | ||
1895 | goto out; | ||
1896 | |||
1897 | if (len <= (PATH_MAX - sizeof(*new))) { | ||
1898 | new->name = (char *)(new) + sizeof(*new); | ||
1899 | new->separate = false; | ||
1900 | } else if (len <= PATH_MAX) { | ||
1901 | /* this looks odd, but is due to final_putname() */ | ||
1902 | struct filename *new2; | ||
1903 | |||
1904 | new2 = kmalloc(sizeof(*new2), GFP_KERNEL); | ||
1905 | if (unlikely(!new2)) { | ||
1906 | __putname(new); | ||
1907 | goto out; | ||
1908 | } | ||
1909 | new2->name = (char *)new; | ||
1910 | new2->separate = true; | ||
1911 | new = new2; | ||
1912 | } else { | ||
1913 | /* we should never get here, but let's be safe */ | ||
1914 | __putname(new); | ||
1915 | goto out; | ||
1916 | } | ||
1917 | strlcpy((char *)new->name, name->name, len); | ||
1918 | new->uptr = NULL; | ||
1919 | new->aname = n; | ||
1920 | n->name = new; | ||
1921 | n->name_put = true; | ||
1922 | } | 1816 | } |
1817 | |||
1923 | out: | 1818 | out: |
1924 | if (parent) { | 1819 | if (parent) { |
1925 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; | 1820 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; |
@@ -1934,6 +1829,11 @@ out: | |||
1934 | audit_copy_inode(n, dentry, inode); | 1829 | audit_copy_inode(n, dentry, inode); |
1935 | } | 1830 | } |
1936 | 1831 | ||
1832 | void __audit_file(const struct file *file) | ||
1833 | { | ||
1834 | __audit_inode(NULL, file->f_path.dentry, 0); | ||
1835 | } | ||
1836 | |||
1937 | /** | 1837 | /** |
1938 | * __audit_inode_child - collect inode info for created/removed objects | 1838 | * __audit_inode_child - collect inode info for created/removed objects |
1939 | * @parent: inode of dentry parent | 1839 | * @parent: inode of dentry parent |
@@ -1965,11 +1865,16 @@ void __audit_inode_child(const struct inode *parent, | |||
1965 | 1865 | ||
1966 | /* look for a parent entry first */ | 1866 | /* look for a parent entry first */ |
1967 | list_for_each_entry(n, &context->names_list, list) { | 1867 | list_for_each_entry(n, &context->names_list, list) { |
1968 | if (!n->name || n->type != AUDIT_TYPE_PARENT) | 1868 | if (!n->name || |
1869 | (n->type != AUDIT_TYPE_PARENT && | ||
1870 | n->type != AUDIT_TYPE_UNKNOWN)) | ||
1969 | continue; | 1871 | continue; |
1970 | 1872 | ||
1971 | if (n->ino == parent->i_ino && | 1873 | if (n->ino == parent->i_ino && n->dev == parent->i_sb->s_dev && |
1972 | !audit_compare_dname_path(dname, n->name->name, n->name_len)) { | 1874 | !audit_compare_dname_path(dname, |
1875 | n->name->name, n->name_len)) { | ||
1876 | if (n->type == AUDIT_TYPE_UNKNOWN) | ||
1877 | n->type = AUDIT_TYPE_PARENT; | ||
1973 | found_parent = n; | 1878 | found_parent = n; |
1974 | break; | 1879 | break; |
1975 | } | 1880 | } |
@@ -1978,11 +1883,8 @@ void __audit_inode_child(const struct inode *parent, | |||
1978 | /* is there a matching child entry? */ | 1883 | /* is there a matching child entry? */ |
1979 | list_for_each_entry(n, &context->names_list, list) { | 1884 | list_for_each_entry(n, &context->names_list, list) { |
1980 | /* can only match entries that have a name */ | 1885 | /* can only match entries that have a name */ |
1981 | if (!n->name || n->type != type) | 1886 | if (!n->name || |
1982 | continue; | 1887 | (n->type != type && n->type != AUDIT_TYPE_UNKNOWN)) |
1983 | |||
1984 | /* if we found a parent, make sure this one is a child of it */ | ||
1985 | if (found_parent && (n->name != found_parent->name)) | ||
1986 | continue; | 1888 | continue; |
1987 | 1889 | ||
1988 | if (!strcmp(dname, n->name->name) || | 1890 | if (!strcmp(dname, n->name->name) || |
@@ -1990,6 +1892,8 @@ void __audit_inode_child(const struct inode *parent, | |||
1990 | found_parent ? | 1892 | found_parent ? |
1991 | found_parent->name_len : | 1893 | found_parent->name_len : |
1992 | AUDIT_NAME_FULL)) { | 1894 | AUDIT_NAME_FULL)) { |
1895 | if (n->type == AUDIT_TYPE_UNKNOWN) | ||
1896 | n->type = type; | ||
1993 | found_child = n; | 1897 | found_child = n; |
1994 | break; | 1898 | break; |
1995 | } | 1899 | } |
@@ -2014,10 +1918,10 @@ void __audit_inode_child(const struct inode *parent, | |||
2014 | if (found_parent) { | 1918 | if (found_parent) { |
2015 | found_child->name = found_parent->name; | 1919 | found_child->name = found_parent->name; |
2016 | found_child->name_len = AUDIT_NAME_FULL; | 1920 | found_child->name_len = AUDIT_NAME_FULL; |
2017 | /* don't call __putname() */ | 1921 | found_child->name->refcnt++; |
2018 | found_child->name_put = false; | ||
2019 | } | 1922 | } |
2020 | } | 1923 | } |
1924 | |||
2021 | if (inode) | 1925 | if (inode) |
2022 | audit_copy_inode(found_child, dentry, inode); | 1926 | audit_copy_inode(found_child, dentry, inode); |
2023 | else | 1927 | else |
@@ -2400,7 +2304,6 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm, | |||
2400 | struct audit_aux_data_bprm_fcaps *ax; | 2304 | struct audit_aux_data_bprm_fcaps *ax; |
2401 | struct audit_context *context = current->audit_context; | 2305 | struct audit_context *context = current->audit_context; |
2402 | struct cpu_vfs_cap_data vcaps; | 2306 | struct cpu_vfs_cap_data vcaps; |
2403 | struct dentry *dentry; | ||
2404 | 2307 | ||
2405 | ax = kmalloc(sizeof(*ax), GFP_KERNEL); | 2308 | ax = kmalloc(sizeof(*ax), GFP_KERNEL); |
2406 | if (!ax) | 2309 | if (!ax) |
@@ -2410,9 +2313,7 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm, | |||
2410 | ax->d.next = context->aux; | 2313 | ax->d.next = context->aux; |
2411 | context->aux = (void *)ax; | 2314 | context->aux = (void *)ax; |
2412 | 2315 | ||
2413 | dentry = dget(bprm->file->f_dentry); | 2316 | get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps); |
2414 | get_vfs_caps_from_disk(dentry, &vcaps); | ||
2415 | dput(dentry); | ||
2416 | 2317 | ||
2417 | ax->fcap.permitted = vcaps.permitted; | 2318 | ax->fcap.permitted = vcaps.permitted; |
2418 | ax->fcap.inheritable = vcaps.inheritable; | 2319 | ax->fcap.inheritable = vcaps.inheritable; |
@@ -2434,7 +2335,7 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm, | |||
2434 | * @new: the new credentials | 2335 | * @new: the new credentials |
2435 | * @old: the old (current) credentials | 2336 | * @old: the old (current) credentials |
2436 | * | 2337 | * |
2437 | * Record the aguments userspace sent to sys_capset for later printing by the | 2338 | * Record the arguments userspace sent to sys_capset for later printing by the |
2438 | * audit system if applicable | 2339 | * audit system if applicable |
2439 | */ | 2340 | */ |
2440 | void __audit_log_capset(const struct cred *new, const struct cred *old) | 2341 | void __audit_log_capset(const struct cred *new, const struct cred *old) |