diff options
-rw-r--r-- | kernel/audit.c | 71 |
1 files changed, 48 insertions, 23 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index e6d88635032c..dae3570b3a3b 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -692,7 +692,8 @@ static void audit_log_vformat(struct audit_buffer *ab, const char *fmt, | |||
692 | goto out; | 692 | goto out; |
693 | len = vsnprintf(skb->tail, avail, fmt, args2); | 693 | len = vsnprintf(skb->tail, avail, fmt, args2); |
694 | } | 694 | } |
695 | skb_put(skb, (len < avail) ? len : avail); | 695 | if (len > 0) |
696 | skb_put(skb, len); | ||
696 | out: | 697 | out: |
697 | return; | 698 | return; |
698 | } | 699 | } |
@@ -710,20 +711,47 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...) | |||
710 | va_end(args); | 711 | va_end(args); |
711 | } | 712 | } |
712 | 713 | ||
713 | void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len) | 714 | /* This function will take the passed buf and convert it into a string of |
715 | * ascii hex digits. The new string is placed onto the skb. */ | ||
716 | void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, | ||
717 | size_t len) | ||
714 | { | 718 | { |
715 | int i; | 719 | int i, avail, new_len; |
720 | unsigned char *ptr; | ||
721 | struct sk_buff *skb; | ||
722 | static const unsigned char *hex = "0123456789ABCDEF"; | ||
723 | |||
724 | BUG_ON(!ab->skb); | ||
725 | skb = ab->skb; | ||
726 | avail = skb_tailroom(skb); | ||
727 | new_len = len<<1; | ||
728 | if (new_len >= avail) { | ||
729 | /* Round the buffer request up to the next multiple */ | ||
730 | new_len = AUDIT_BUFSIZ*(((new_len-avail)/AUDIT_BUFSIZ) + 1); | ||
731 | avail = audit_expand(ab, new_len); | ||
732 | if (!avail) | ||
733 | return; | ||
734 | } | ||
716 | 735 | ||
717 | for (i=0; i<len; i++) | 736 | ptr = skb->tail; |
718 | audit_log_format(ab, "%02x", buf[i]); | 737 | for (i=0; i<len; i++) { |
738 | *ptr++ = hex[(buf[i] & 0xF0)>>4]; /* Upper nibble */ | ||
739 | *ptr++ = hex[buf[i] & 0x0F]; /* Lower nibble */ | ||
740 | } | ||
741 | *ptr = 0; | ||
742 | skb_put(skb, len << 1); /* new string is twice the old string */ | ||
719 | } | 743 | } |
720 | 744 | ||
745 | /* This code will escape a string that is passed to it if the string | ||
746 | * contains a control character, unprintable character, double quote mark, | ||
747 | * or a space. Unescaped strings will start and end with a double quote mark. | ||
748 | * Strings that are escaped are printed in hex (2 digits per char). */ | ||
721 | void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) | 749 | void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) |
722 | { | 750 | { |
723 | const unsigned char *p = string; | 751 | const unsigned char *p = string; |
724 | 752 | ||
725 | while (*p) { | 753 | while (*p) { |
726 | if (*p == '"' || *p == ' ' || *p < 0x20 || *p > 0x7f) { | 754 | if (*p == '"' || *p < 0x21 || *p > 0x7f) { |
727 | audit_log_hex(ab, string, strlen(string)); | 755 | audit_log_hex(ab, string, strlen(string)); |
728 | return; | 756 | return; |
729 | } | 757 | } |
@@ -732,31 +760,28 @@ void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) | |||
732 | audit_log_format(ab, "\"%s\"", string); | 760 | audit_log_format(ab, "\"%s\"", string); |
733 | } | 761 | } |
734 | 762 | ||
735 | 763 | /* This is a helper-function to print the escaped d_path */ | |
736 | /* This is a helper-function to print the d_path without using a static | ||
737 | * buffer or allocating another buffer in addition to the one in | ||
738 | * audit_buffer. */ | ||
739 | void audit_log_d_path(struct audit_buffer *ab, const char *prefix, | 764 | void audit_log_d_path(struct audit_buffer *ab, const char *prefix, |
740 | struct dentry *dentry, struct vfsmount *vfsmnt) | 765 | struct dentry *dentry, struct vfsmount *vfsmnt) |
741 | { | 766 | { |
742 | char *p; | 767 | char *p, *path; |
743 | struct sk_buff *skb = ab->skb; | ||
744 | int len, avail; | ||
745 | 768 | ||
746 | if (prefix) | 769 | if (prefix) |
747 | audit_log_format(ab, " %s", prefix); | 770 | audit_log_format(ab, " %s", prefix); |
748 | 771 | ||
749 | avail = skb_tailroom(skb); | 772 | /* We will allow 11 spaces for ' (deleted)' to be appended */ |
750 | p = d_path(dentry, vfsmnt, skb->tail, avail); | 773 | path = kmalloc(PATH_MAX+11, GFP_KERNEL); |
751 | if (IS_ERR(p)) { | 774 | if (!path) { |
752 | /* FIXME: can we save some information here? */ | 775 | audit_log_format(ab, "<no memory>"); |
753 | audit_log_format(ab, "<toolong>"); | 776 | return; |
754 | } else { | ||
755 | /* path isn't at start of buffer */ | ||
756 | len = ((char *)skb->tail + avail - 1) - p; | ||
757 | memmove(skb->tail, p, len); | ||
758 | skb_put(skb, len); | ||
759 | } | 777 | } |
778 | p = d_path(dentry, vfsmnt, path, PATH_MAX+11); | ||
779 | if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */ | ||
780 | /* FIXME: can we save some information here? */ | ||
781 | audit_log_format(ab, "<too long>"); | ||
782 | } else | ||
783 | audit_log_untrustedstring(ab, p); | ||
784 | kfree(path); | ||
760 | } | 785 | } |
761 | 786 | ||
762 | /* Remove queued messages from the audit_txlist and send them to user space. */ | 787 | /* Remove queued messages from the audit_txlist and send them to user space. */ |