1 /*
2  *   Copyright (c) 2015 Fujitsu Ltd.
3  *   Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
4  *
5  *   This program is free software;  you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  *   the GNU General Public License for more details.
14  */
15 
16 /*
17  * This is a test for glibc bug:
18  * https://www.qualys.com/research/security-advisories/GHOST-CVE-2015-0235.txt
19  */
20 
21 #include <netdb.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include "test.h"
27 
28 #define CANARY "in_the_coal_mine"
29 
30 static void setup(void);
31 static void check_vulnerable(void);
32 
33 static struct {
34 	char buffer[1024];
35 	char canary[sizeof(CANARY)];
36 } temp = {
37 	"buffer",
38 	CANARY,
39 };
40 
41 char *TCID = "gethostbyname_r01";
42 int TST_TOTAL = 1;
43 
44 int main(int ac, char **av)
45 {
46 	int lc;
47 
48 	tst_parse_opts(ac, av, NULL, NULL);
49 
50 	setup();
51 
52 	for (lc = 0; TEST_LOOPING(lc); lc++) {
53 		tst_count = 0;
54 		check_vulnerable();
55 	}
56 
57 	tst_exit();
58 }
59 
60 static void setup(void)
61 {
62 	tst_sig(NOFORK, DEF_HANDLER, NULL);
63 	TEST_PAUSE;
64 }
65 
66 static void check_vulnerable(void)
67 {
68 	struct hostent resbuf;
69 	struct hostent *result;
70 	int herrno;
71 	int retval;
72 	char name[sizeof(temp.buffer)];
73 	size_t len;
74 
75 	/*
76 	 * <glibc>/nss/digits_dots.c:
77 	 * strlen(name) = size_needed - sizeof(*host_addr) -
78 	 *                sizeof(*h_addr_ptrs) - 1;
79 	 */
80 	len = sizeof(temp.buffer) - 16 - 2 * sizeof(char *) - 1;
81 	memset(name, '0', len);
82 	name[len] = '\0';
83 
84 	retval = gethostbyname_r(name, &resbuf, temp.buffer,
85 				 sizeof(temp.buffer), &result, &herrno);
86 
87 	if (strcmp(temp.canary, CANARY) != 0) {
88 		tst_resm(TFAIL, "vulnerable");
89 		return;
90 	}
91 
92 	if (retval == ERANGE) {
93 		tst_resm(TPASS, "not vulnerable");
94 		return;
95 	}
96 
97 	tst_resm(TFAIL, "gethostbyname_r() returned %s, expected ERANGE",
98 		 tst_strerrno(retval));
99 }
100