diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/audit.c | 10 | ||||
| -rw-r--r-- | kernel/auditfilter.c | 23 | ||||
| -rw-r--r-- | kernel/auditsc.c | 49 |
3 files changed, 58 insertions, 24 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index f8f203e8018c..72ab759a0b43 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -429,7 +429,7 @@ static void kauditd_send_skb(struct sk_buff *skb) | |||
| 429 | * This function doesn't consume an skb as might be expected since it has to | 429 | * This function doesn't consume an skb as might be expected since it has to |
| 430 | * copy it anyways. | 430 | * copy it anyways. |
| 431 | */ | 431 | */ |
| 432 | static void kauditd_send_multicast_skb(struct sk_buff *skb) | 432 | static void kauditd_send_multicast_skb(struct sk_buff *skb, gfp_t gfp_mask) |
| 433 | { | 433 | { |
| 434 | struct sk_buff *copy; | 434 | struct sk_buff *copy; |
| 435 | struct audit_net *aunet = net_generic(&init_net, audit_net_id); | 435 | struct audit_net *aunet = net_generic(&init_net, audit_net_id); |
| @@ -448,11 +448,11 @@ static void kauditd_send_multicast_skb(struct sk_buff *skb) | |||
| 448 | * no reason for new multicast clients to continue with this | 448 | * no reason for new multicast clients to continue with this |
| 449 | * non-compliance. | 449 | * non-compliance. |
| 450 | */ | 450 | */ |
| 451 | copy = skb_copy(skb, GFP_KERNEL); | 451 | copy = skb_copy(skb, gfp_mask); |
| 452 | if (!copy) | 452 | if (!copy) |
| 453 | return; | 453 | return; |
| 454 | 454 | ||
| 455 | nlmsg_multicast(sock, copy, 0, AUDIT_NLGRP_READLOG, GFP_KERNEL); | 455 | nlmsg_multicast(sock, copy, 0, AUDIT_NLGRP_READLOG, gfp_mask); |
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | /* | 458 | /* |
| @@ -1100,7 +1100,7 @@ static void audit_receive(struct sk_buff *skb) | |||
| 1100 | } | 1100 | } |
| 1101 | 1101 | ||
| 1102 | /* Run custom bind function on netlink socket group connect or bind requests. */ | 1102 | /* Run custom bind function on netlink socket group connect or bind requests. */ |
| 1103 | static int audit_bind(int group) | 1103 | static int audit_bind(struct net *net, int group) |
| 1104 | { | 1104 | { |
| 1105 | if (!capable(CAP_AUDIT_READ)) | 1105 | if (!capable(CAP_AUDIT_READ)) |
| 1106 | return -EPERM; | 1106 | return -EPERM; |
| @@ -1940,7 +1940,7 @@ void audit_log_end(struct audit_buffer *ab) | |||
| 1940 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); | 1940 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); |
| 1941 | 1941 | ||
| 1942 | nlh->nlmsg_len = ab->skb->len; | 1942 | nlh->nlmsg_len = ab->skb->len; |
| 1943 | kauditd_send_multicast_skb(ab->skb); | 1943 | kauditd_send_multicast_skb(ab->skb, ab->gfp_mask); |
| 1944 | 1944 | ||
| 1945 | /* | 1945 | /* |
| 1946 | * The original kaudit unicast socket sends up messages with | 1946 | * The original kaudit unicast socket sends up messages with |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 3598e13f2a65..4f68a326d92e 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -442,19 +442,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 442 | if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) { | 442 | if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) { |
| 443 | f->type = AUDIT_LOGINUID_SET; | 443 | f->type = AUDIT_LOGINUID_SET; |
| 444 | f->val = 0; | 444 | f->val = 0; |
| 445 | } | 445 | entry->rule.pflags |= AUDIT_LOGINUID_LEGACY; |
| 446 | |||
| 447 | if ((f->type == AUDIT_PID) || (f->type == AUDIT_PPID)) { | ||
| 448 | struct pid *pid; | ||
| 449 | rcu_read_lock(); | ||
| 450 | pid = find_vpid(f->val); | ||
| 451 | if (!pid) { | ||
| 452 | rcu_read_unlock(); | ||
| 453 | err = -ESRCH; | ||
| 454 | goto exit_free; | ||
| 455 | } | ||
| 456 | f->val = pid_nr(pid); | ||
| 457 | rcu_read_unlock(); | ||
| 458 | } | 446 | } |
| 459 | 447 | ||
| 460 | err = audit_field_valid(entry, f); | 448 | err = audit_field_valid(entry, f); |
| @@ -630,6 +618,13 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) | |||
| 630 | data->buflen += data->values[i] = | 618 | data->buflen += data->values[i] = |
| 631 | audit_pack_string(&bufp, krule->filterkey); | 619 | audit_pack_string(&bufp, krule->filterkey); |
| 632 | break; | 620 | break; |
| 621 | case AUDIT_LOGINUID_SET: | ||
| 622 | if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) { | ||
| 623 | data->fields[i] = AUDIT_LOGINUID; | ||
| 624 | data->values[i] = AUDIT_UID_UNSET; | ||
| 625 | break; | ||
| 626 | } | ||
| 627 | /* fallthrough if set */ | ||
| 633 | default: | 628 | default: |
| 634 | data->values[i] = f->val; | 629 | data->values[i] = f->val; |
| 635 | } | 630 | } |
| @@ -646,6 +641,7 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) | |||
| 646 | int i; | 641 | int i; |
| 647 | 642 | ||
| 648 | if (a->flags != b->flags || | 643 | if (a->flags != b->flags || |
| 644 | a->pflags != b->pflags || | ||
| 649 | a->listnr != b->listnr || | 645 | a->listnr != b->listnr || |
| 650 | a->action != b->action || | 646 | a->action != b->action || |
| 651 | a->field_count != b->field_count) | 647 | a->field_count != b->field_count) |
| @@ -764,6 +760,7 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old) | |||
| 764 | new = &entry->rule; | 760 | new = &entry->rule; |
| 765 | new->vers_ops = old->vers_ops; | 761 | new->vers_ops = old->vers_ops; |
| 766 | new->flags = old->flags; | 762 | new->flags = old->flags; |
| 763 | new->pflags = old->pflags; | ||
| 767 | new->listnr = old->listnr; | 764 | new->listnr = old->listnr; |
| 768 | new->action = old->action; | 765 | new->action = old->action; |
| 769 | for (i = 0; i < AUDIT_BITMASK_SIZE; i++) | 766 | for (i = 0; i < AUDIT_BITMASK_SIZE; i++) |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index c75522a83678..072566dd0caf 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -72,6 +72,8 @@ | |||
| 72 | #include <linux/fs_struct.h> | 72 | #include <linux/fs_struct.h> |
| 73 | #include <linux/compat.h> | 73 | #include <linux/compat.h> |
| 74 | #include <linux/ctype.h> | 74 | #include <linux/ctype.h> |
| 75 | #include <linux/string.h> | ||
| 76 | #include <uapi/linux/limits.h> | ||
| 75 | 77 | ||
| 76 | #include "audit.h" | 78 | #include "audit.h" |
| 77 | 79 | ||
| @@ -1861,8 +1863,7 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
| 1861 | } | 1863 | } |
| 1862 | 1864 | ||
| 1863 | list_for_each_entry_reverse(n, &context->names_list, list) { | 1865 | list_for_each_entry_reverse(n, &context->names_list, list) { |
| 1864 | /* does the name pointer match? */ | 1866 | if (!n->name || strcmp(n->name->name, name->name)) |
| 1865 | if (!n->name || n->name->name != name->name) | ||
| 1866 | continue; | 1867 | continue; |
| 1867 | 1868 | ||
| 1868 | /* match the correct record type */ | 1869 | /* match the correct record type */ |
| @@ -1877,12 +1878,48 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
| 1877 | } | 1878 | } |
| 1878 | 1879 | ||
| 1879 | out_alloc: | 1880 | out_alloc: |
| 1880 | /* unable to find the name from a previous getname(). Allocate a new | 1881 | /* unable to find an entry with both a matching name and type */ |
| 1881 | * anonymous entry. | 1882 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); |
| 1882 | */ | ||
| 1883 | n = audit_alloc_name(context, AUDIT_TYPE_NORMAL); | ||
| 1884 | if (!n) | 1883 | if (!n) |
| 1885 | return; | 1884 | 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) { | ||
| 1890 | /* we can't use getname_kernel() due to size limits */ | ||
| 1891 | size_t len = strlen(name->name) + 1; | ||
| 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 | } | ||
| 1886 | out: | 1923 | out: |
| 1887 | if (parent) { | 1924 | if (parent) { |
| 1888 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; | 1925 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; |
