The function calculates new_len as len << 1 for hex encoding. This has two overflow risks: the shift itself can overflow when len is large, and the result can be truncated when assigned to new_len (declared as int) from the size_t calculation. Fix by using check_shl_overflow() to catch shift overflow and changing new_len and loop counter i to size_t to prevent truncation.
Unified · Split
| @@ -62,6 +62,7 @@ · 61 unmodified lines | |||
| 62 | #include <net/ip.h> | 62 | #include <net/ip.h> |
| 63 | #include <net/ipv6.h> | 63 | #include <net/ipv6.h> |
| 64 | #include <linux/sctp.h> | 64 | #include <linux/sctp.h> |
| 65 | #include <linux/overflow.h> | ||
| 65 | 66 | ||
| 66 | #include "audit.h" | 67 | #include "audit.h" |
| 67 | 68 | ||
| @@ -2080,7 +2081,8 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...) · 2012 unmodified lines | |||
| 2080 | void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, | 2081 | void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, |
| 2081 | size_t len) | 2082 | size_t len) |
| 2082 | { | 2083 | { |
| 2083 | int i, avail, new_len; | 2084 | int avail; |
| 2085 | size_t i, new_len; | ||
| 2084 | unsigned char *ptr; | 2086 | unsigned char *ptr; |
| 2085 | struct sk_buff *skb; | 2087 | struct sk_buff *skb; |
| 2086 | 2088 | ||
| @@ -2090,7 +2092,12 @@ void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, · 3 unmodified lines | |||
| 2090 | BUG_ON(!ab->skb); | 2092 | BUG_ON(!ab->skb); |
| 2091 | skb = ab->skb; | 2093 | skb = ab->skb; |
| 2092 | avail = skb_tailroom(skb); | 2094 | avail = skb_tailroom(skb); |
| 2093 | new_len = len<<1; | 2095 | |
| 2096 | if (check_shl_overflow(len, 1, &new_len)) { | ||
| 2097 | audit_log_format(ab, "?"); | ||
| 2098 | return; | ||
| 2099 | } | ||
| 2100 | |||
| 2094 | if (new_len >= avail) { | 2101 | if (new_len >= avail) { |
| 2095 | /* Round the buffer request up to the next multiple */ | 2102 | /* Round the buffer request up to the next multiple */ |
| 2096 | new_len = AUDIT_BUFSIZ*(((new_len-avail)/AUDIT_BUFSIZ) + 1); | 2103 | new_len = AUDIT_BUFSIZ*(((new_len-avail)/AUDIT_BUFSIZ) + 1); |