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 | 62 | #include <net/ip.h> |
| 63 | 63 | #include <net/ipv6.h> |
| 64 | 64 | #include <linux/sctp.h> |
| 65 | +#include <linux/overflow.h> | |
| 65 | 66 | |
| 66 | 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 | 2081 | void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, |
| 2081 | 2082 | size_t len) |
| 2082 | 2083 | { |
| 2083 | − int i, avail, new_len; | |
| 2084 | + int avail; | |
| 2085 | + size_t i, new_len; | |
| 2084 | 2086 | unsigned char *ptr; |
| 2085 | 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 | 2092 | BUG_ON(!ab->skb); |
| 2091 | 2093 | skb = ab->skb; |
| 2092 | 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 | 2101 | if (new_len >= avail) { |
| 2095 | 2102 | /* Round the buffer request up to the next multiple */ |
| 2096 | 2103 | new_len = AUDIT_BUFSIZ*(((new_len-avail)/AUDIT_BUFSIZ) + 1); |