|
From: | Shu-Chun Weng |
Subject: | Re: [PATCH] Fix unsigned integer underflow in fd-trans.c |
Date: | Fri, 18 Oct 2019 11:18:16 -0700 |
Le 18/10/2019 à 02:19, Shu-Chun Weng a écrit :
> In any of these `*_for_each_*` functions, the last entry in the buffer (so the
> "remaining length in the buffer" `len` is equal to the length of the
> entry `nlmsg_len`/`nla_len`/etc) has size that is not a multiple of the
> alignment, the aligned lengths `*_ALIGN(*_len)` will be greater than `len`.
> Since `len` is unsigned (`size_t`), it underflows and the loop will read
> pass the buffer.
>
> This may manifest as random EINVAL or EOPNOTSUPP error on IO or network
> system calls.
>
> Signed-off-by: Shu-Chun Weng <address@hidden>
> ---
> linux-user/fd-trans.c | 51 +++++++++++++++++++++++++++++++++----------
> 1 file changed, 40 insertions(+), 11 deletions(-)
>
> diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c
> index 60077ce531..9b92386abf 100644
> --- a/linux-user/fd-trans.c
> +++ b/linux-user/fd-trans.c
> @@ -279,6 +279,7 @@ static abi_long host_to_target_for_each_nlmsg(struct nlmsghdr *nlh,
> (struct nlmsghdr *))
> {
> uint32_t nlmsg_len;
> + uint32_t aligned_nlmsg_len;
> abi_long ret;
>
> while (len > sizeof(struct nlmsghdr)) {
> @@ -312,8 +313,13 @@ static abi_long host_to_target_for_each_nlmsg(struct nlmsghdr *nlh,
> break;
> }
> tswap_nlmsghdr(nlh);
> - len -= NLMSG_ALIGN(nlmsg_len);
> - nlh = (struct nlmsghdr *)(((char*)nlh) + NLMSG_ALIGN(nlmsg_len));
> +
> + aligned_nlmsg_len = NLMSG_ALIGN(nlmsg_len);
> + if (aligned_nlmsg_len >= len) {
> + break;
> + }
> + len -= aligned_nlmsg_len;
> + nlh = (struct nlmsghdr *)(((char*)nlh) + aligned_nlmsg_len);
> }
> return 0;
> }
Nice catch.
But the first "if" in the loop is already here for that, we only need to
fix it with something like that in all the for_each functions:
@@ -285,7 +285,7 @@ static abi_long host_to_target_for_each_nlmsg(struct
nlmsghdr *nlh,
nlmsg_len = nlh->nlmsg_len;
if (nlmsg_len < sizeof(struct nlmsghdr) ||
- nlmsg_len > len) {
+ NLMSG_ALIGN(nlmsg_len) > len) {
break;
}
Thanks,
Laurent
smime.p7s
Description: S/MIME Cryptographic Signature
[Prev in Thread] | Current Thread | [Next in Thread] |