[LTP] [PATCH] syscalls/setsockopt09: Test use-after-free in socket timer
Martin Doucha
mdoucha@suse.cz
Fri Mar 11 17:33:06 CET 2022
setsockopt09 may also trigger kernel crash in socket timer. Add git hash
for the timer fix and add taint check to detect this failure variant.
Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
.../kernel/syscalls/setsockopt/setsockopt09.c | 68 ++++++++++++-------
1 file changed, 44 insertions(+), 24 deletions(-)
diff --git a/testcases/kernel/syscalls/setsockopt/setsockopt09.c b/testcases/kernel/syscalls/setsockopt/setsockopt09.c
index 4b1ce2e92..3047ec0ff 100644
--- a/testcases/kernel/syscalls/setsockopt/setsockopt09.c
+++ b/testcases/kernel/syscalls/setsockopt/setsockopt09.c
@@ -19,6 +19,11 @@
*
* net/packet: rx_owner_map depends on pg_vec
*
+ * commit c800aaf8d869f2b9b47b10c5c312fe19f0a94042
+ * Author: WANG Cong <xiyou.wangcong@gmail.com>
+ * Date: Mon Jul 24 10:07:32 2017 -0700
+ *
+ * packet: fix use-after-free in prb_retire_rx_blk_timer_expired()
*/
#define _GNU_SOURCE
@@ -50,41 +55,55 @@ static void setup(void)
static void run(void)
{
- unsigned int version = TPACKET_V3;
+ unsigned int i, version = TPACKET_V3;
struct tpacket_req3 req = {
.tp_block_size = 4 * pagesize,
- .tp_block_nr = 256,
.tp_frame_size = TPACKET_ALIGNMENT << 7,
.tp_retire_blk_tov = 64,
.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH
};
- req.tp_frame_nr = req.tp_block_size * req.tp_block_nr;
- req.tp_frame_nr /= req.tp_frame_size;
-
- sock = SAFE_SOCKET(AF_PACKET, SOCK_RAW, 0);
- TEST(setsockopt(sock, SOL_PACKET, PACKET_VERSION, &version,
- sizeof(version)));
+ for (i = 0; i < 5; i++) {
+ req.tp_block_nr = 256;
+ req.tp_frame_nr = req.tp_block_size * req.tp_block_nr;
+ req.tp_frame_nr /= req.tp_frame_size;
+
+ sock = SAFE_SOCKET(AF_PACKET, SOCK_RAW, 0);
+ TEST(setsockopt(sock, SOL_PACKET, PACKET_VERSION, &version,
+ sizeof(version)));
+
+ if (TST_RET == -1 && TST_ERR == EINVAL)
+ tst_brk(TCONF | TTERRNO, "TPACKET_V3 not supported");
+
+ if (TST_RET) {
+ tst_brk(TBROK | TTERRNO,
+ "setsockopt(PACKET_VERSION, TPACKET_V3)");
+ }
+
+ /* Allocate owner map and then free it again */
+ SAFE_SETSOCKOPT(sock, SOL_PACKET, PACKET_RX_RING, &req,
+ sizeof(req));
+ req.tp_block_nr = 0;
+ req.tp_frame_nr = 0;
+ SAFE_SETSOCKOPT(sock, SOL_PACKET, PACKET_RX_RING, &req,
+ sizeof(req));
+
+ /* Switch packet version and trigger double free of owner map */
+ SAFE_SETSOCKOPT_INT(sock, SOL_PACKET, PACKET_VERSION,
+ TPACKET_V2);
+ SAFE_SETSOCKOPT(sock, SOL_PACKET, PACKET_RX_RING, &req,
+ sizeof(req));
+ SAFE_CLOSE(sock);
- if (TST_RET == -1 && TST_ERR == EINVAL)
- tst_brk(TCONF | TTERRNO, "TPACKET_V3 not supported");
+ /* Wait for socket timer to expire just in case */
+ usleep(req.tp_retire_blk_tov * 3000);
- if (TST_RET) {
- tst_brk(TBROK | TTERRNO,
- "setsockopt(PACKET_VERSION, TPACKET_V3)");
+ if (tst_taint_check()) {
+ tst_res(TFAIL, "Kernel is vulnerable");
+ return;
+ }
}
- /* Allocate owner map and then free it again */
- SAFE_SETSOCKOPT(sock, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req));
- req.tp_block_nr = 0;
- req.tp_frame_nr = 0;
- SAFE_SETSOCKOPT(sock, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req));
-
- /* Switch interface version and trigger double free of owner map */
- SAFE_SETSOCKOPT_INT(sock, SOL_PACKET, PACKET_VERSION, TPACKET_V2);
- SAFE_SETSOCKOPT(sock, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req));
- SAFE_CLOSE(sock);
-
tst_res(TPASS, "Nothing bad happened, probably");
}
@@ -111,6 +130,7 @@ static struct tst_test test = {
},
.tags = (const struct tst_tag[]) {
{"linux-git", "ec6af094ea28"},
+ {"linux-git", "c800aaf8d869"},
{"CVE", "2021-22600"},
{}
}
--
2.35.1
More information about the ltp
mailing list