From f048de6c7bdd432f5da5b50c4d9a3f0b1cd5dbfabbd733b469cd5c7df002093d Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Thu, 13 Sep 2012 09:04:36 +0000 Subject: [PATCH] Accepting request 133636 from home:vitezslav_cizek:branches:network - added rules for SuSEfirewall2 (bnc#729793) - use the "su" logrotate directive (bnc#677335) - prevent the sorcerer's apprentice syndrome situation only when explicitly specified by the user (bnc#774376) (added a new command line option --prevent-sas to turn it on) - fix a race condition where two server threads pick up a single client, which causes the transported file being overwritten (bnc#599856) OBS-URL: https://build.opensuse.org/request/show/133636 OBS-URL: https://build.opensuse.org/package/show/network/atftp?expand=0&rev=16 --- atftp-0.7-prevent-sas.patch | 219 ++++++++++++++++++++++++++++ atftp-0.7-server_receive_race.patch | 102 +++++++++++++ atftp.changes | 24 +++ atftp.fw | 5 + atftp.spec | 12 ++ atftpd.logrotate | 1 + 6 files changed, 363 insertions(+) create mode 100644 atftp-0.7-prevent-sas.patch create mode 100644 atftp-0.7-server_receive_race.patch create mode 100644 atftp.fw diff --git a/atftp-0.7-prevent-sas.patch b/atftp-0.7-prevent-sas.patch new file mode 100644 index 0000000..89adb46 --- /dev/null +++ b/atftp-0.7-prevent-sas.patch @@ -0,0 +1,219 @@ +Index: atftp-0.7/tftpd.c +=================================================================== +--- atftp-0.7.orig/tftpd.c 2012-09-11 13:55:28.303292010 +0200 ++++ atftp-0.7/tftpd.c 2012-09-11 13:58:20.701437613 +0200 +@@ -62,6 +62,7 @@ int retry_timeout = S_TIMEOUT; + + int tftpd_daemon = 0; /* By default we are started by inetd */ + int tftpd_daemon_no_fork = 0; /* For who want a false daemon mode */ ++int tftpd_prevent_sas = 0; /* For who don't want the sorcerer's apprentice syndrome */ + short tftpd_port = 0; /* Port atftpd listen to */ + char tftpd_addr[MAXLEN] = ""; /* IP address atftpd binds to */ + +@@ -833,6 +834,7 @@ int tftpd_cmd_line_options(int argc, cha + { "mtftp", 1, NULL, OPT_MTFTP }, + { "mtftp-port", 1, NULL, OPT_MTFTP_PORT }, + #endif ++ { "prevent-sas", 0, NULL, 'X' }, + { "no-source-port-checking", 0, NULL, OPT_PORT_CHECK }, + { "mcast-switch-client", 0, NULL, OPT_MCAST_SWITCH }, + { "version", 0, NULL, 'V' }, +@@ -896,6 +898,9 @@ int tftpd_cmd_line_options(int argc, cha + case 'N': + tftpd_daemon_no_fork = 1; + break; ++ case 'X': ++ tftpd_prevent_sas = 1; ++ break; + case 'U': + tmp = strtok(optarg, "."); + if (tmp != NULL) +@@ -1120,6 +1125,7 @@ void tftpd_usage(void) + " --pidfile : write PID to this file\n" + " --daemon : run atftpd standalone (no inetd)\n" + " --no-fork : run as a daemon, don't fork\n" ++ " --prevent-sas : prevent Sorcerer's Apprentice Syndrome\n" + " --user : default is nobody\n" + " --group : default is nogroup\n" + " --port : port on which atftp listen\n" +Index: atftp-0.7/tftpd_file.c +=================================================================== +--- atftp-0.7.orig/tftpd_file.c 2012-09-11 13:55:28.405295054 +0200 ++++ atftp-0.7/tftpd_file.c 2012-09-11 13:55:28.422295562 +0200 +@@ -55,6 +55,7 @@ + extern char directory[MAXLEN]; + /* read only except for the main thread */ + extern int tftpd_cancel; ++extern int tftpd_prevent_sas; + + #ifdef HAVE_PCRE + extern tftpd_pcre_self_t *pcre_top; +@@ -863,31 +864,31 @@ int tftpd_send_file(struct thread_data * + logger(LOG_DEBUG, "received ACK ", block_number); + } + +- /* check whether the block request isn't already fulfilled */ +- +- /* multicast, block numbers could contain gaps */ +- if (multicast) { +- if (last_requested_block >= block_number) +- { +- if (data->trace) +- logger(LOG_DEBUG, "received duplicated ACK = %d>", last_requested_block, block_number); +- break; +- } +- else +- last_requested_block = block_number; +- /* unicast, blocks should be requested one after another */ +- } else { +- if (last_requested_block + 1 != block_number && last_requested_block != -1) +- { +- if (data->trace) +- logger(LOG_DEBUG, "received out of order ACK ", last_requested_block + 1, block_number); +- break; ++ /* if turned on, check whether the block request isn't already fulfilled */ ++ if (tftpd_prevent_sas) { ++ /* multicast, block numbers could contain gaps */ ++ if (multicast) { ++ if (last_requested_block >= block_number) ++ { ++ if (data->trace) ++ logger(LOG_DEBUG, "received duplicated ACK = %d>", last_requested_block, block_number); ++ break; ++ } ++ else ++ last_requested_block = block_number; ++ /* unicast, blocks should be requested one after another */ ++ } else { ++ if (last_requested_block + 1 != block_number && last_requested_block != -1) ++ { ++ if (data->trace) ++ logger(LOG_DEBUG, "received out of order ACK ", last_requested_block + 1, block_number); ++ break; ++ } ++ else ++ last_requested_block = block_number; + } +- else +- last_requested_block = block_number; + } + +- + if (ntohs(tftphdr->th_block) == 65535) + { + block_loops++; +Index: atftp-0.7/tftp_file.c +=================================================================== +--- atftp-0.7.orig/tftp_file.c 2012-09-11 13:55:28.387294518 +0200 ++++ atftp-0.7/tftp_file.c 2012-09-11 13:55:28.422295562 +0200 +@@ -49,6 +49,7 @@ + #define NB_BLOCK 2048 + + extern int tftp_cancel; ++extern int tftp_prevent_sas; + + /* + * Find a hole in the file bitmap. +@@ -767,15 +768,18 @@ int tftp_send_file(struct client_data *d + } + block_number = ntohs(tftphdr->th_block); + +- if (last_requested_block >= block_number) +- { +- if (data->trace) +- fprintf(stderr, "received duplicated ACK = %ld>\n", +- last_requested_block, block_number); +- break; ++ /* if turned on, check whether the block request isn't already fulfilled */ ++ if (tftp_prevent_sas) { ++ if (last_requested_block >= block_number) ++ { ++ if (data->trace) ++ fprintf(stderr, "received duplicated ACK = %ld>\n", ++ last_requested_block, block_number); ++ break; ++ } ++ else ++ last_requested_block = block_number; + } +- else +- last_requested_block = block_number; + + if (data->trace) + fprintf(stderr, "received ACK \n", +Index: atftp-0.7/tftp.c +=================================================================== +--- atftp-0.7.orig/tftp.c 2012-09-11 13:55:28.255290577 +0200 ++++ atftp-0.7/tftp.c 2012-09-11 14:01:13.437593304 +0200 +@@ -57,6 +57,7 @@ + /* defined as extern in tftp_file.c and mtftp_file.c, set by the signal + handler */ + int tftp_cancel = 0; ++int tftp_prevent_sas = 0; + + /* local flags */ + int interactive = 1; /* if false, we run in batch mode */ +@@ -982,6 +983,7 @@ int tftp_cmd_line_options(int argc, char + #endif + { "mtftp", 1, NULL, '1'}, + { "no-source-port-checking", 0, NULL, '0'}, ++ { "prevent-sas", 0, NULL, 'X'}, + { "verbose", 0, NULL, 'v'}, + { "trace", 0, NULL, 'd'}, + #if DEBUG +@@ -1086,6 +1088,9 @@ int tftp_cmd_line_options(int argc, char + case '0': + data.checkport = 0; + break; ++ case 'X': ++ tftp_prevent_sas = 1; ++ break; + case 'v': + snprintf(string, sizeof(string), "verbose on"); + make_arg(string, &ac, &av); +@@ -1182,6 +1187,7 @@ void tftp_usage(void) + " --mtftp <\"name value\"> : set mtftp variable to value\n" + #endif + " --no-source-port-checking: violate RFC, see man page\n" ++ " --prevent-sas : prevent Sorcerer's Apprentice Syndrome\n" + " --verbose : set verbose mode on\n" + " --trace : set trace mode on\n" + #if DEBUG +Index: atftp-0.7/atftpd.8 +=================================================================== +--- atftp-0.7.orig/atftpd.8 2004-03-06 21:41:40.000000000 +0100 ++++ atftp-0.7/atftpd.8 2012-09-11 13:55:28.423295591 +0200 +@@ -180,6 +180,14 @@ implication. Be aware that this option v + option has effect only for non-multicast transfer. + + .TP ++.B \-\-prevent\-sas ++Address the Sorcerer's Apprentice Syndrome situation as requested by RFC 1350. ++This RFC requires repeated responses to a single packet to be ++rejected. Thus a block will only get retransmitted on a timeout. ++For backward compatibility, the default stays to ignore this RFC. ++So blocks get transmitted on every request. ++ ++.TP + .B \-\-mcast\-switch\-client + This option allow the server to proceed with the next multicast client + as soon as the current client timeout. When the current master client +Index: atftp-0.7/atftp.1 +=================================================================== +--- atftp-0.7.orig/atftp.1 2004-03-06 21:41:40.000000000 +0100 ++++ atftp-0.7/atftp.1 2012-09-11 13:55:28.423295591 +0200 +@@ -77,6 +77,14 @@ to configure client side port to use. + See atftpd's man page. + + .TP ++.B \-\-prevent\-sas ++Address the Sorcerer's Apprentice Syndrome situation as requested by RFC 1350. ++This RFC requires repeated responses to a single packet to be ++rejected. Thus a block will only get retransmitted on a timeout. ++For backward compatibility, the default stays to ignore this RFC. ++So blocks get transmitted on every request. ++ ++.TP + .B \-\-verbose + Instruct atftp to be verbose. It will print more information about + what's going on. diff --git a/atftp-0.7-server_receive_race.patch b/atftp-0.7-server_receive_race.patch new file mode 100644 index 0000000..53833bb --- /dev/null +++ b/atftp-0.7-server_receive_race.patch @@ -0,0 +1,102 @@ +Index: tftpd_file.c +=================================================================== +--- tftpd_file.c.orig 2012-08-06 10:26:36.356745154 +0200 ++++ tftpd_file.c 2012-08-06 11:27:59.265571512 +0200 +@@ -113,7 +113,7 @@ int tftpd_receive_file(struct thread_dat + struct sockaddr_in *sa = &data->client_info->client; + struct sockaddr_in from; + struct tftphdr *tftphdr = (struct tftphdr *)data->data_buffer; +- FILE *fp; ++ FILE *fp = NULL; + char filename[MAXLEN]; + char string[MAXLEN]; + int timeout = data->timeout; +@@ -143,18 +143,6 @@ int tftpd_receive_file(struct thread_dat + return ERR; + } + +- /* Open the file for writing. */ +- if ((fp = fopen(filename, "w")) == NULL) +- { +- /* Can't create the file. */ +- logger(LOG_INFO, "Can't open %s for writing", filename); +- tftp_send_error(sockfd, sa, EACCESS, data->data_buffer, data->data_buffer_size); +- if (data->trace) +- logger(LOG_DEBUG, "sent ERROR ", EACCESS, +- tftp_errmsg[EACCESS]); +- return ERR; +- } +- + /* tsize option */ + if (((result = opt_get_tsize(data->tftp_options)) > -1) && !convert) + { +@@ -171,7 +159,6 @@ int tftpd_receive_file(struct thread_dat + if (data->trace) + logger(LOG_DEBUG, "sent ERROR ", EOPTNEG, + tftp_errmsg[EOPTNEG]); +- fclose(fp); + return ERR; + } + timeout = result; +@@ -188,7 +175,6 @@ int tftpd_receive_file(struct thread_dat + if (data->trace) + logger(LOG_DEBUG, "sent ERROR ", EOPTNEG, + tftp_errmsg[EOPTNEG]); +- fclose(fp); + return ERR; + } + +@@ -198,7 +184,6 @@ int tftpd_receive_file(struct thread_dat + if (data->data_buffer == NULL) + { + logger(LOG_ERR, "memory allocation failure"); +- fclose(fp); + return ERR; + } + tftphdr = (struct tftphdr *)data->data_buffer; +@@ -209,7 +194,6 @@ int tftpd_receive_file(struct thread_dat + if (data->trace) + logger(LOG_DEBUG, "sent ERROR ", ENOSPACE, + tftp_errmsg[ENOSPACE]); +- fclose(fp); + return ERR; + } + opt_set_blksize(result, data->tftp_options); +@@ -342,6 +326,20 @@ int tftpd_receive_file(struct thread_dat + } + break; + case S_DATA_RECEIVED: ++ if (fp == NULL) { ++ /* Open the file for writing. */ ++ if ((fp = fopen(filename, "w")) == NULL) ++ { ++ /* Can't create the file. */ ++ logger(LOG_INFO, "Can't open %s for writing", filename); ++ tftp_send_error(sockfd, sa, EACCESS, data->data_buffer, data->data_buffer_size); ++ if (data->trace) ++ logger(LOG_DEBUG, "sent ERROR ", EACCESS, ++ tftp_errmsg[EACCESS]); ++ return ERR; ++ } ++ } ++ + /* We need to seek to the right place in the file */ + block_number = ntohs(tftphdr->th_block); + if (data->trace) +@@ -369,13 +367,13 @@ int tftpd_receive_file(struct thread_dat + state = S_SEND_ACK; + break; + case S_END: +- fclose(fp); ++ if (fp != NULL) fclose(fp); + return OK; + case S_ABORT: +- fclose(fp); ++ if (fp != NULL) fclose(fp); + return ERR; + default: +- fclose(fp); ++ if (fp != NULL) fclose(fp); + logger(LOG_ERR, "%s: %d: tftpd_file.c: huh?", + __FILE__, __LINE__); + return ERR; diff --git a/atftp.changes b/atftp.changes index f01c8a1..659f92a 100644 --- a/atftp.changes +++ b/atftp.changes @@ -1,3 +1,27 @@ +------------------------------------------------------------------- +Tue Sep 11 13:01:20 UTC 2012 - vcizek@suse.com + +- added rules for SuSEfirewall2 (bnc#729793) + +------------------------------------------------------------------- +Tue Sep 11 12:47:04 UTC 2012 - vcizek@suse.com + +- use the "su" logrotate directive (bnc#677335) + +------------------------------------------------------------------- +Wed Sep 5 14:10:03 UTC 2012 - vcizek@suse.com + +- prevent the sorcerer's apprentice syndrome situation only when + explicitly specified by the user (bnc#774376) + (added a new command line option --prevent-sas to turn it on) + +------------------------------------------------------------------- +Wed Jan 11 15:27:36 UTC 2012 - vcizek@suse.com + +- fix a race condition where two server threads pick up a single + client, which causes the transported file being overwritten + (bnc#599856) + ------------------------------------------------------------------- Mon Jan 2 17:28:19 UTC 2012 - vcizek@suse.cz diff --git a/atftp.fw b/atftp.fw new file mode 100644 index 0000000..5c09d36 --- /dev/null +++ b/atftp.fw @@ -0,0 +1,5 @@ +## Name: aTFTP Server +## Description: Opens ports for tftp service. + +# space separated list of allowed UDP ports +UDP="tftp" diff --git a/atftp.spec b/atftp.spec index 708fd19..7f06d12 100644 --- a/atftp.spec +++ b/atftp.spec @@ -14,7 +14,10 @@ # Please submit bugfixes or comments via http://bugs.opensuse.org/ # + + # +%define _fwdefdir /etc/sysconfig/SuSEfirewall2.d/services %define pkg_version 0.7 Name: atftp @@ -28,6 +31,7 @@ Source: %{name}-%{pkg_version}.tar.bz2 Source1: atftpd.init.d Source2: atftpd.sysconfig Source3: atftpd.logrotate +Source4: atftp.fw Patch1: atftp-0.7.dif Patch2: atftp-CLK_TCK.diff Patch3: atftp-0.7_compiler_warnings.patch @@ -38,6 +42,9 @@ Patch7: atftpd-0.7_unprotected_assignments_crash.patch Patch8: atftpd-0.7_circumvent_tftp_size_restrictions.patch # PATCH-FIX-SUSE sorcerer's apprentice syndrom (bnc#727843) Patch9: atftp-0.7-sorcerers_apprentice.patch +# PATCH-FIX-SUSE server receive thread race (bnc#599856) +Patch10: atftp-0.7-server_receive_race.patch +Patch11: atftp-0.7-prevent-sas.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build PreReq: %insserv_prereq %fillup_prereq PreReq: pwdutils @@ -69,6 +76,8 @@ boot of hundreds of machines simultaneously. %patch7 %patch8 %patch9 -p1 +%patch10 -p0 +%patch11 -p1 %build autoreconf -fi @@ -82,6 +91,8 @@ make %{?_smp_mflags} %{__ln_s} -f ../../etc/init.d/atftpd %{buildroot}%{_sbindir}/rcatftpd %{__install} -D -m 0644 %{S:2} %{buildroot}/var/adm/fillup-templates/sysconfig.atftpd %{__install} -D -m 0644 %{S:3} %{buildroot}/etc/logrotate.d/%{name} +%{__mkdir} -p %{buildroot}/%{_fwdefdir} +%{__install} -m 0644 %{S:4} %{buildroot}/%{_fwdefdir}/atftp %{__install} -d -m 0750 %{buildroot}/srv/tftpboot %{__install} -d -m 0750 %{buildroot}/var/log/atftpd @@ -122,6 +133,7 @@ fi %{_mandir}/man1/atftp.1.gz %{_mandir}/man8/atftpd.8.gz %{_mandir}/man8/in.tftpd.8.gz +%config %{_fwdefdir}/atftp %dir %attr(0750,root,tftp) /srv/tftpboot %dir %attr(0750,tftp,root) /var/log/atftpd/ diff --git a/atftpd.logrotate b/atftpd.logrotate index 0b6bc38..9b5c384 100644 --- a/atftpd.logrotate +++ b/atftpd.logrotate @@ -1,4 +1,5 @@ /var/log/atftpd/atftp.log { + su tftp tftp compress dateext maxage 365