Subject: Deadlock with icmpv6fuzz

From: Eric Sesterhenn <[email-masked]>
Date: Tue, 20 Jan 2009 21:47:43 +0100

Hi,

I can get my box into a deadlock when running "icmpv6fuzz -r 25668",
source code is attached

# CONFIG_CLASSIC_RCU is not set
CONFIG_TREE_RCU=y
# CONFIG_PREEMPT_RCU is not set
CONFIG_RCU_TRACE=y
CONFIG_RCU_FANOUT=32
# CONFIG_RCU_FANOUT_EXACT is not set
CONFIG_TREE_RCU_TRACE=y
# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_RCU_TORTURE_TEST=m
CONFIG_RCU_CPU_STALL_DETECTOR=y

CONFIG_IPV6=m
CONFIG_IPV6_PRIVACY=y
# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_IPV6_OPTIMISTIC_DAD is not set
# CONFIG_IPV6_MIP6 is not set
CONFIG_IPV6_SIT=m
CONFIG_IPV6_NDISC_NODETYPE=y
CONFIG_IPV6_TUNNEL=m
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_IPV6_MROUTE is not set
CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_IP6_NF_MATCH_IPV6HEADER=m

Kernel is current -git

[ 5459.100023] INFO: RCU detected CPU 0 stall (t=2500 jiffies)
[ 5459.100023] Pid: 25668, comm: icmpv6fuzz Not tainted 2.6.29-rc2 #92
[ 5459.100023] Call Trace:
[ 5459.100023]  [<c0629676>] ? printk+0x18/0x1a
[ 5459.100023]  [<c016db22>] __rcu_pending+0x62/0x250
[ 5459.100023]  [<c014c55b>] ? trace_hardirqs_off+0xb/0x10
[ 5459.100023]  [<c016dd22>] rcu_pending+0x12/0x40
[ 5459.100023]  [<c0132b8a>] update_process_times+0x2a/0x60
[ 5459.100023]  [<c014a115>] tick_sched_timer+0x55/0xc0
[ 5459.100023]  [<c014a0c0>] ? tick_sched_timer+0x0/0xc0
[ 5459.100023]  [<c01409b0>] __run_hrtimer+0x70/0xe0
[ 5459.100023]  [<c014a0c0>] ? tick_sched_timer+0x0/0xc0
[ 5459.100023]  [<c014118d>] hrtimer_interrupt+0xed/0x190
[ 5459.100023]  [<c010597b>] timer_interrupt+0x3b/0x50
[ 5459.100023]  [<c016ac19>] handle_IRQ_event+0x29/0x60
[ 5459.100023]  [<c016c9a5>] handle_level_irq+0x65/0xe0
[ 5459.100023]  [<c016c940>] ? handle_level_irq+0x0/0xe0
[ 5459.100023]  <IRQ>  [<c014e9b1>] ? trace_hardirqs_on_caller+0x151/0x1c0
[ 5459.100023]  [<c0103bac>] ? common_interrupt+0x2c/0x34
[ 5459.100023]  [<c014007b>] ? posix_cpu_clock_get+0xb/0x160
[ 5459.100023]  [<d18a6e87>] ? ipv6_push_exthdr+0x17/0x70 [ipv6]
[ 5459.100023]  [<c0570aaf>] ? skb_store_bits+0x10f/0x200
[ 5459.100023]  [<d18a6f03>] ? ipv6_push_frag_opts+0x23/0x30 [ipv6]
[ 5459.100023]  [<d18858ab>] ? ip6_push_pending_frames+0x21b/0x3e0 [ipv6]
[ 5459.100023]  [<d189b01a>] ? rawv6_sendmsg+0xbfa/0xc70 [ipv6]
[ 5459.100023]  [<c05f0494>] ? inet_sendmsg+0x34/0x60
[ 5459.100023]  [<c056a909>] ? sock_sendmsg+0xe9/0x110
[ 5459.100023]  [<c013d800>] ? autoremove_wake_function+0x0/0x50
[ 5459.100023]  [<c018db96>] ? might_fault+0x46/0xa0
[ 5459.100023]  [<c018dbe1>] ? might_fault+0x91/0xa0
[ 5459.100023]  [<c018db96>] ? might_fault+0x46/0xa0
[ 5459.100023]  [<c031aa65>] ? copy_from_user+0x35/0x130
[ 5459.100023]  [<c056ac55>] ? sys_sendto+0xa5/0xd0
[ 5459.100023]  [<c018db96>] ? might_fault+0x46/0xa0
[ 5459.100023]  [<c0568fb0>] ? sock_ioctl+0x0/0x240
[ 5459.100023]  [<c018db96>] ? might_fault+0x46/0xa0
[ 5459.100023]  [<c056b28b>] ? sys_socketcall+0x18b/0x2a0
[ 5459.100023]  [<c0103551>] ? sysenter_do_call+0x12/0x31
[ 5489.100020] INFO: RCU detected CPU 0 stall (t=10000 jiffies)
[ 5489.100020] Pid: 25668, comm: icmpv6fuzz Not tainted 2.6.29-rc2 #92
[ 5489.100020] Call Trace:
[ 5489.100020]  [<c0629676>] ? printk+0x18/0x1a
[ 5489.100020]  [<c016db22>] __rcu_pending+0x62/0x250
[ 5489.100020]  [<c014c55b>] ? trace_hardirqs_off+0xb/0x10
[ 5489.100020]  [<c016dd22>] rcu_pending+0x12/0x40
[ 5489.100020]  [<c0132b8a>] update_process_times+0x2a/0x60
[ 5489.100020]  [<c014a115>] tick_sched_timer+0x55/0xc0
[ 5489.100020]  [<c014a0c0>] ? tick_sched_timer+0x0/0xc0
[ 5489.100020]  [<c01409b0>] __run_hrtimer+0x70/0xe0
[ 5489.100020]  [<c014a0c0>] ? tick_sched_timer+0x0/0xc0
[ 5489.100020]  [<c014118d>] hrtimer_interrupt+0xed/0x190
[ 5489.100020]  [<c010597b>] timer_interrupt+0x3b/0x50
[ 5489.100020]  [<c016ac19>] handle_IRQ_event+0x29/0x60
[ 5489.100020]  [<c016c9a5>] handle_level_irq+0x65/0xe0
[ 5489.100020]  [<c016c940>] ? handle_level_irq+0x0/0xe0
[ 5489.100020]  <IRQ>  [<c014e9b1>] ? trace_hardirqs_on_caller+0x151/0x1c0
[ 5489.100020]  [<c0103bac>] ? common_interrupt+0x2c/0x34
[ 5489.100020]  [<c014007b>] ? posix_cpu_clock_get+0xb/0x160
[ 5489.100020]  [<d18a6e87>] ? ipv6_push_exthdr+0x17/0x70 [ipv6]
[ 5489.100020]  [<c0570aaf>] ? skb_store_bits+0x10f/0x200
[ 5489.100020]  [<d18a6f03>] ? ipv6_push_frag_opts+0x23/0x30 [ipv6]
[ 5489.100020]  [<d18858ab>] ? ip6_push_pending_frames+0x21b/0x3e0 [ipv6]
[ 5489.100020]  [<d189b01a>] ? rawv6_sendmsg+0xbfa/0xc70 [ipv6]
[ 5489.100020]  [<c05f0494>] ? inet_sendmsg+0x34/0x60
[ 5489.100020]  [<c056a909>] ? sock_sendmsg+0xe9/0x110
[ 5489.100020]  [<c013d800>] ? autoremove_wake_function+0x0/0x50
[ 5489.100020]  [<c018db96>] ? might_fault+0x46/0xa0
[ 5489.100020]  [<c018dbe1>] ? might_fault+0x91/0xa0
[ 5489.100020]  [<c018db96>] ? might_fault+0x46/0xa0
[ 5489.100020]  [<c031aa65>] ? copy_from_user+0x35/0x130
[ 5489.100020]  [<c056ac55>] ? sys_sendto+0xa5/0xd0
[ 5489.100020]  [<c018db96>] ? might_fault+0x46/0xa0
[ 5489.100020]  [<c0568fb0>] ? sock_ioctl+0x0/0x240
[ 5489.100020]  [<c018db96>] ? might_fault+0x46/0xa0
[ 5489.100020]  [<c056b28b>] ? sys_socketcall+0x18b/0x2a0
[ 5489.100020]  [<c0103551>] ? sysenter_do_call+0x12/0x31

and so on

(gdb) l*(ipv6_push_exthdr+0x17)
0x4d7 is in ipv6_push_exthdr (net/ipv6/exthdrs.c:700).
695		*proto = NEXTHDR_ROUTING;
696	}
697	
698	static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
699	{
700		struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
701	
702		memcpy(h, opt, ipv6_optlen(opt));
703		h->nexthdr = *proto;
704		*proto = type;

(gdb) l*(skb_store_bits+0x10f)
0x282f is in skb_store_bits (net/core/skbuff.c:1567).
1562				vaddr = kmap_skb_frag(frag);
1563				memcpy(vaddr + frag->page_offset + offset - start,
1564				       from, copy);
1565				kunmap_skb_frag(vaddr);
1566	
1567				if ((len -= copy) == 0)
1568					return 0;
1569				offset += copy;
1570				from += copy;
1571			}

(gdb) l*(ipv6_push_frag_opts+0x23)
0x553 is in ipv6_push_frag_opts (net/ipv6/exthdrs.c:730).
725	
726	void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
727	{
728		if (opt->dst1opt)
729			ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
730	}
731	
732	struct ipv6_txoptions *
733	ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
734	{

Running the same command on a different box with a different config

[11237.306574] skb_under_panic: text:c071d473 len:2361 put:864 head:ca7510c0 data:ca750f10 tail:0xca751270 end:0xca751280 dev:<NULL>
[11237.306909] ------------[ cut here ]------------
[11237.307002] kernel BUG at net/core/skbuff.c:147!
[11237.307045] invalid opcode: 0000 [#1] PREEMPT DEBUG_PAGEALLOC
[11237.307045] last sysfs file: /sys/class/vc/vcsa50/dev
[11237.307045] Modules linked in: [last unloaded: rcutorture]
[11237.307045] 
[11237.307045] Pid: 19951, comm: icmpv6fuzz Not tainted (2.6.29-rc2-00021-gd84d31c #216) System Name
[11237.307045] EIP: 0060:[<c06918e1>] EFLAGS: 00010246 CPU: 0
[11237.307045] EIP is at skb_under_panic+0x3f/0x46
[11237.307045] EAX: 00000088 EBX: c098dafb ECX: c012413f EDX: c012476a
[11237.307045] ESI: 00000000 EDI: ca5b5ccc EBP: ca5b5c68 ESP: ca5b5c3c
[11237.307045]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
[11237.307045] Process icmpv6fuzz (pid: 19951, ti=ca5b5000 task=c2aa0000 task.ti=ca5b5000)
[11237.307045] Stack:
[11237.307045]  c09d321a c071d473 00000939 00000360 ca7510c0 ca750f10 ca751270 ca751280
[11237.307045]  c098dafb cce2e620 c724c0cc ca5b5c74 c0692b30 ca5b5cd3 ca5b5c90 c071d473
[11237.307045]  0000003c ca5b5c90 cce2e620 cedc11b4 ca5b5ccc ca5b5ca0 c071d4c5 c724c0cc
[11237.307045] Call Trace:
[11237.307045]  [<c071d473>] ? ipv6_push_exthdr+0x26/0x55
[11237.307045]  [<c0692b30>] ? skb_push+0x2c/0x35
[11237.307045]  [<c071d473>] ? ipv6_push_exthdr+0x26/0x55
[11237.307045]  [<c071d4c5>] ? ipv6_push_frag_opts+0x23/0x29
[11237.307045]  [<c0701a8a>] ? ip6_push_pending_frames+0x1b2/0x39b
[11237.307045]  [<c07145b1>] ? rawv6_sendmsg+0xa84/0xb17
[11237.307045]  [<c013ec6d>] ? put_lock_stats+0xd/0x21
[11237.307045]  [<c013ec6d>] ? put_lock_stats+0xd/0x21
[11237.307045]  [<c013ed20>] ? lock_release_holdtime+0x9f/0xa7
[11237.307045]  [<c06db84a>] ? inet_sendmsg+0x40/0x4d
[11237.307045]  [<c068db41>] ? sock_sendmsg+0xce/0xe5
[11237.307045]  [<c013ec6d>] ? put_lock_stats+0xd/0x21
[11237.307045]  [<c013416c>] ? autoremove_wake_function+0x0/0x35
[11237.307045]  [<c0142df7>] ? lock_release_non_nested+0xb0/0x1f8
[11237.307045]  [<c017ccb3>] ? might_fault+0x4f/0x8b
[11237.307045]  [<c017ccb3>] ? might_fault+0x4f/0x8b
[11237.307045]  [<c068e4a1>] ? sys_sendto+0xa9/0xc8
[11237.307045]  [<c013ec6d>] ? put_lock_stats+0xd/0x21
[11237.307045]  [<c013ed20>] ? lock_release_holdtime+0x9f/0xa7
[11237.307045]  [<c07b2557>] ? sub_preempt_count+0xc0/0xd1
[11237.307045]  [<c013ec6d>] ? put_lock_stats+0xd/0x21
[11237.307045]  [<c013ed20>] ? lock_release_holdtime+0x9f/0xa7
[11237.307045]  [<c0142df7>] ? lock_release_non_nested+0xb0/0x1f8
[11237.307045]  [<c017ccb3>] ? might_fault+0x4f/0x8b
[11237.307045]  [<c068ec3d>] ? sys_socketcall+0xeb/0x180
[11237.307045]  [<c0102ea1>] ? sysenter_do_call+0x12/0x31
[11237.307045] Code: 0f 45 de 53 ff b0 94 00 00 00 ff b0 90 00 00 00 ff b0 9c 00 00 00 ff b0 98 00 00 00 52 ff 70 50 51 68 1a 32 9d c0 e8 6f 2e a9 ff <0f> 0b 83 c4 24 eb fe 55 89 e5 56 53 0f 1f 44 00 00 8b 70 14 bb 
[11237.307045] EIP: [<c06918e1>] skb_under_panic+0x3f/0x46 SS:ESP 0068:ca5b5c3c
[11237.374079] ---[ end trace 7188985726996093 ]---

(gdb) l *(ipv6_push_exthdr+0x26)
0xc071d473 is in ipv6_push_exthdr (net/ipv6/exthdrs.c:700).
695		*proto = NEXTHDR_ROUTING;
696	}
697	
698	static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
699	{
700		struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));
701	
702		memcpy(h, opt, ipv6_optlen(opt));
703		h->nexthdr = *proto;
704		*proto = type;

----------------8<------------------------

/*
 * ICMPv6 or ICMPv4 socket fuzzer.
 *
 * Copyright (c) 2006, Clément Lecigne
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <net/if.h>
//#include <net/if_var.h>
#include <sys/uio.h>
//#include <netinet6/ip6_mroute.h>
//#include <netinet6/in6_var.h>

#define SIOCGETMIFCNT_IN6       SIOCPROTOPRIVATE        /* IP protocol privates */
#define SIOCGETSGCNT_IN6        (SIOCPROTOPRIVATE+1)
#define SIOCGETRPF      (SIOCPROTOPRIVATE+2)

/* functions */
unsigned int randaddr(void);
void randsoopt(int);
void randgoopt(int);
void randioctl(int);
void usage(char *);

/*
* boucle until we hit a valid socket option
*/
void randsoopt(int sock)
{
	unsigned int optval;
	int optlen, optname, level, ret, on = rand() % 2;
	do
	{
		switch (rand() % 5)
		{
			case 0:
				level = IPPROTO_IPV6;
				break;
			case 1:
				level = SOL_SOCKET;
				break;
			case 2:
				level = IPPROTO_RAW;
				break;
			case 3:
				level = rand() & 0xFF;
				break;
			case 4:
				level = IPPROTO_IP;
				break;
		}
		
		if (rand() % 6)
		{
			optlen = rand();
			optval = (unsigned int)randaddr();
		}
		else
		{
		/* 
			* In some cases, kernel excepts that
			* optlen == sizeof (int) and that's
			* the first bound checking.
			*/
			optlen = sizeof (int);
			on = rand();
			optval = (unsigned int)&on;
		}
		
		if (rand() % 8)
			optname = rand() % 255;
		else
			optname = rand();
#if 0
		/*
		 * anti well know FreeBSD mbufs exhaustion.
		 */
		if (optname == 25 || optname == IPV6_IPSEC_POLICY || 
				optname == IPV6_FW_ADD || optname == IPV6_FW_FLUSH
				|| optname == IPV6_FW_DEL || optname == IPV6_FW_ZERO)
			continue;
		/*printf("level : %d - optname : %d - optlen : %d\n", 
				level, optname, optlen);*/
#endif
		ret = setsockopt(sock, level, optname, (void *)optval, optlen);

	}while(ret == -1);
	return;
}

/*
* ioctl ipv6 socket fuzzer.
*/
void randioctl(int sock)
{
	unsigned long reqs[] = { SIOCGETSGCNT_IN6, SIOCGETMIFCNT_IN6,
		SIOCGETRPF};
/*
		GSCOPE6DEF, SIOCGLIFADDR, SIOCSIFPHYADDR_IN6, SIOCGIFNETMASK_IN6,
		SIOCAIFADDR_IN6, SIOCGIFDSTADDR_IN6, SIOCSIFALIFETIME_IN6, 
		SIOCGIFADDR_IN6, SIOCGIFDSTADDR_IN6, SIOCGIFNETMASK_IN6, SIOCGIFAFLAG_IN6,
		SIOCGIFSTAT_IN6, SIOCGIFSTAT_ICMP6, SIOCGIFALIFETIME_IN6, SIOCSIFALIFETIME_IN6,
		SIOCAIFADDR_IN6, SIOCDIFADDR_IN6 }; */
	unsigned int arg;
	int ret;
	unsigned long request;
	
	if (rand() % 8)
		request = reqs[rand() % (sizeof (reqs) / sizeof (reqs[0]))];
	else
		request = rand() + rand();
	if (rand() % 2)
	{
		arg = randaddr();
		ret = ioctl(sock, request, (caddr_t)arg);
	}
	else
	{
		arg = rand();
		ret = ioctl(sock, request, (int)arg);
	}
}

/*
* return a random address
*/
unsigned int randaddr(void)
{
	char *p = malloc(1);
	unsigned int heap = (unsigned int)p;
	free(p);
	switch (rand() % 4)
	{
		case 0:
			return (heap + (rand() & 0xFFF));
		case 1:
			return ((unsigned int)&heap + (rand() & 0xFFF));
		case 2:
			return (0xc0000000 + (rand() & 0xFFFF));
		case 3:
			return (rand());
	}
	return (0);
}

int main(int ac, char **av) 
{
	int32_t cc, s, occ, i, j, a, try, count, opts;
	u_int32_t seed, maxsize;
	u_int8_t ip6;
	char c, *buf;
	struct addrinfo *res, hints;
	struct sockaddr_in6 from;
	socklen_t fromlen;
	struct msghdr msg;
	struct cmsghdr *cmsg = NULL;
	struct iovec iov;
	
	/* default values */
	seed = getpid();
	count = 50;
	occ = 10000;
	maxsize = 4096;
	opts = 50;
	ip6 = 1;
	fromlen = sizeof(from);
	
	if (getuid())
	{
		fprintf(stderr, " - you must be root.\n");
		exit(EXIT_FAILURE);
	}
	
	while ((c = getopt(ac, av, "r:n:c:m:o:46")) != EOF)
	{
		switch (c)
		{
			case '6':
				ip6 = 1;
				break;
			case '4':
				ip6 = 0;
				break;
			case 'r':
				seed = atoi(optarg);
				break;
			case 'n':
				occ = atoi(optarg);
				break;
			case 'c':
				count = atoi(optarg);
				break;
			case 'm':
				maxsize = atoi(optarg);
				break;
			case 'o':
				opts = atoi(optarg);
				break;
			default:
				usage(av[0]);
				break;
		}
	}
	
	printf("seeding with %u\n", seed);
	srand(seed);

	buf = malloc(maxsize);
	if (buf == NULL)
	{
		printf("%s: out of memory.\n", av[0]);
		exit(EXIT_FAILURE);
	}

	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = AI_CANONNAME;
	hints.ai_socktype = SOCK_RAW;
	
	if(ip6)
	{
		hints.ai_family = AF_INET6;
		hints.ai_protocol = IPPROTO_ICMPV6;
		getaddrinfo("::1", NULL, &hints, &res); 
	}
	else
	{
		hints.ai_family = AF_INET;
		hints.ai_protocol = IPPROTO_ICMP;
		getaddrinfo("127.0.0.1", NULL, &hints, &res);
	}

	for (i = 0; i < occ; i++)
	{
		printf(".\n");
		s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		//cc = bind(s, res->ai_addr, res->ai_addrlen);

		for (j = 0; j < opts; j++)
		{
			randsoopt(s);
			//randgoopt(s);
			randioctl(s);

			for (a = 0; a < 32; a++)
				buf[a] = rand() % 255;

			try = 0;
			do
			{
				switch(rand() % 3)
				{
				case 0:
					cc = sendto(s, buf, rand() % maxsize, 0,
							(struct sockaddr *)res->ai_addr, res->ai_addrlen);
					break;
				case 1:
				case 2:
					msg.msg_controllen = (rand() % 2) ? rand() & maxsize : 0;
					if (msg.msg_controllen)
					{
						if (msg.msg_controllen < sizeof (struct cmsghdr))
							cmsg = (struct cmsghdr *)malloc(sizeof (struct cmsghdr));
						else
							cmsg = (struct cmsghdr *)malloc(msg.msg_controllen);
						if (cmsg == NULL) goto nocmsghdr;
						msg.msg_control = cmsg;
						cmsg->cmsg_level = (rand() % 2) ? IPPROTO_IPV6 : rand();
						cmsg->cmsg_type = (rand() % 2) ? rand() % 255 : rand();
						cmsg->cmsg_len = (rand() % 2) ? msg.msg_controllen : rand();
					}
					else
					{
nocmsghdr:
						msg.msg_control = (rand() % 5) ? NULL : (void*)randaddr();
						msg.msg_controllen = (rand() % 2) ? rand() : 0;
					}
					iov.iov_len = (rand() % 2) ? rand() : rand() & maxsize;
					iov.iov_base = (rand() % 2) ? (void*)randaddr() : &buf;
					msg.msg_iov = (rand() % 2) ? (void*)randaddr() : &iov;
					if (rand() % 5)
					{
						msg.msg_name = res->ai_addr;
						msg.msg_namelen = res->ai_addrlen;
					}
					else
					{
						msg.msg_name = (caddr_t)randaddr();
						msg.msg_namelen = rand();
					}
					msg.msg_flags = rand();
					cc = sendmsg (s, &msg, rand());
				}
				if (cmsg != NULL)
				{	
				//	free(cmsg);
				//	cmsg = NULL;
				}
				try++;
			} while(cc == -1 && try != count); 
			recvmsg(s, &msg, MSG_DONTWAIT);
		}
		close(s);
	}
	free(buf);
	freeaddrinfo(res);
	exit(EXIT_SUCCESS);
}

/* 
* usage
*/
void usage(char *prog)
{
	printf("usage: %s [-4] [-6] [-r seed] [-c sendto-timeout]\n"
		"          [-m maxsize] [-o maxsetsockopt] [-n occ]\n", prog);
	exit(EXIT_FAILURE);
}