Check link carrier via ifch and netlink instead of ioctl.
Thus, ioctl can once again be removed from the ndhc seccomp whitelist.
This commit is contained in:
		| @@ -261,7 +261,7 @@ static int arp_send(struct client_state_t cs[static 1], | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     if (!check_carrier(cs->arpFd)) { | ||||
|     if (check_carrier()) { | ||||
|         log_error("%s: (%s) carrier down; sendto would fail", | ||||
|                   client_config.interface, __func__); | ||||
|         ret = -99; | ||||
|   | ||||
							
								
								
									
										20
									
								
								src/dhcp.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/dhcp.c
									
									
									
									
									
								
							| @@ -108,7 +108,7 @@ static ssize_t send_dhcp_unicast(struct client_state_t cs[static 1], | ||||
|     } | ||||
|     size_t payload_len = | ||||
|         sizeof *payload - (sizeof payload->options - 1 - endloc); | ||||
|     if (!check_carrier(fd)) { | ||||
|     if (check_carrier()) { | ||||
|         log_error("%s: (%s) carrier down; write would fail", | ||||
|                   client_config.interface, __func__); | ||||
|         ret = -99; | ||||
| @@ -228,22 +228,6 @@ static ssize_t get_raw_packet(struct client_state_t cs[static 1], | ||||
|     return l; | ||||
| } | ||||
|  | ||||
| int check_carrier(int fd) | ||||
| { | ||||
|     struct ifreq ifr; | ||||
|     memset(&ifr, 0, sizeof ifr); | ||||
|     memcpy(ifr.ifr_name, client_config.interface, | ||||
|            sizeof client_config.interface); | ||||
|     if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) { | ||||
|         log_error("%s: (%s) ioctl failed: %s", client_config.interface, | ||||
|                   __func__, strerror(errno)); | ||||
|         return 0; | ||||
|     } | ||||
|     if ((ifr.ifr_flags & IFF_RUNNING) && (ifr.ifr_flags & IFF_UP)) | ||||
|         return 1; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| // Broadcast a DHCP message using a raw socket. | ||||
| static ssize_t send_dhcp_raw(struct dhcpmsg payload[static 1]) | ||||
| { | ||||
| @@ -302,7 +286,7 @@ static ssize_t send_dhcp_raw(struct dhcpmsg payload[static 1]) | ||||
|         .sll_halen = 6, | ||||
|     }; | ||||
|     memcpy(da.sll_addr, "\xff\xff\xff\xff\xff\xff", 6); | ||||
|     if (!check_carrier(fd)) { | ||||
|     if (check_carrier()) { | ||||
|         log_error("%s: (%s) carrier down; sendto would fail", | ||||
|                   client_config.interface, __func__); | ||||
|         ret = -99; | ||||
|   | ||||
| @@ -91,6 +91,4 @@ ssize_t send_rebind(struct client_state_t cs[static 1]); | ||||
| ssize_t send_decline(struct client_state_t cs[static 1], uint32_t server); | ||||
| ssize_t send_release(struct client_state_t cs[static 1]); | ||||
|  | ||||
| int check_carrier(int fd); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -225,6 +225,14 @@ static int ifchwrite(const char buf[static 1], size_t count) | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| // Returns 0 if there is a carrier, -1 if not. | ||||
| int check_carrier(void) | ||||
| { | ||||
|     char buf[256]; | ||||
|     snprintf(buf, sizeof buf, "carrier:;"); | ||||
|     return ifchwrite(buf, strlen(buf)); | ||||
| } | ||||
|  | ||||
| int ifchange_deconfig(struct client_state_t cs[static 1]) | ||||
| { | ||||
|     char buf[256]; | ||||
|   | ||||
| @@ -29,6 +29,7 @@ | ||||
| #ifndef IFCHANGE_H_ | ||||
| #define IFCHANGE_H_ | ||||
|  | ||||
| int check_carrier(void); | ||||
| int ifchange_bind(struct client_state_t cs[static 1], | ||||
|                   struct dhcpmsg packet[static 1]); | ||||
| int ifchange_deconfig(struct client_state_t cs[static 1]); | ||||
|   | ||||
| @@ -141,6 +141,7 @@ static int perform_ip4set(const char buf[static 1], size_t len) | ||||
|         case STATE_MTU: cmdf |= perform_mtu(tb, arg_len); break; | ||||
|         case STATE_NTPSVR: cmdf |= perform_ntpsrv(tb, arg_len); break; | ||||
|         case STATE_WINS: cmdf |= perform_wins(tb, arg_len); break; | ||||
|         case STATE_CARRIER: cmdf |= perform_carrier(); break; | ||||
|         default: | ||||
|             log_line("error: invalid state in dispatch_work"); | ||||
|             return -99; | ||||
| @@ -170,8 +171,9 @@ static int perform_ip4set(const char buf[static 1], size_t len) | ||||
|     cmd_s32 = ('tzone:' % { cl.state = STATE_TIMEZONE; }) s32_arg; | ||||
|     cmd_u16 = ('mtu:' % { cl.state = STATE_MTU; }) u16_arg; | ||||
|     cmd_u8  = ('ipttl:' % { cl.state = STATE_IPTTL; }) u8_arg; | ||||
|     cmd_none = ('carrier:' % { cl.state = STATE_CARRIER; }) terminator; | ||||
|  | ||||
|     command = (cmd_ip|cmd_ip4set|cmd_iplist|cmd_str|cmd_s32|cmd_u16|cmd_u8); | ||||
|     command = (cmd_ip|cmd_ip4set|cmd_iplist|cmd_str|cmd_s32|cmd_u16|cmd_u8|cmd_none); | ||||
|     main := (command > Reset)+; | ||||
| }%% | ||||
|  | ||||
|   | ||||
| @@ -16,7 +16,8 @@ enum ifchd_states { | ||||
|     STATE_IPTTL, | ||||
|     STATE_MTU, | ||||
|     STATE_NTPSVR, | ||||
|     STATE_WINS | ||||
|     STATE_WINS, | ||||
|     STATE_CARRIER, | ||||
| }; | ||||
|  | ||||
| #include <net/if.h> | ||||
|   | ||||
							
								
								
									
										21
									
								
								src/ifset.c
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								src/ifset.c
									
									
									
									
									
								
							| @@ -327,6 +327,27 @@ static int link_flags_get(int fd, uint32_t flags[static 1]) | ||||
|     return -4; | ||||
| } | ||||
|  | ||||
| int perform_carrier(void) | ||||
| { | ||||
|     int ret = -1; | ||||
|     uint32_t flags; | ||||
|     int fd = socket(AF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, NETLINK_ROUTE); | ||||
|     if (fd < 0) { | ||||
|         log_error("%s: (%s) netlink socket open failed: %s", | ||||
|                   client_config.interface, __func__, strerror(errno)); | ||||
|         goto fail; | ||||
|     } | ||||
|  | ||||
|     if (link_flags_get(fd, &flags) < 0) | ||||
|         goto fail_fd;; | ||||
|     if ((flags & IFF_RUNNING) && (flags & IFF_UP)) | ||||
|         ret = 0; | ||||
| fail_fd: | ||||
|     close(fd); | ||||
| fail: | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static int link_set_flags(int fd, uint32_t flags) | ||||
| { | ||||
|     uint32_t oldflags; | ||||
|   | ||||
| @@ -28,6 +28,7 @@ | ||||
|  | ||||
| #ifndef NJK_IFSET_H_ | ||||
| #define NJK_IFSET_H_ | ||||
| int perform_carrier(void); | ||||
| int perform_ifup(void); | ||||
| int perform_ip_subnet_bcast(const char str_ipaddr[static 1], | ||||
|                             const char str_subnet[static 1], | ||||
|   | ||||
| @@ -83,11 +83,6 @@ int enforce_seccomp_ndhc(void) | ||||
|         ALLOW_SYSCALL(mmap), | ||||
|         ALLOW_SYSCALL(munmap), | ||||
|  | ||||
|         // For checking to see if the interface carrier is up.  Should be | ||||
|         // removed in favor of synchronous requests to ifchd, but it will | ||||
|         // work for now. | ||||
|         ALLOW_SYSCALL(ioctl), | ||||
|  | ||||
|         ALLOW_SYSCALL(rt_sigreturn), | ||||
| #ifdef __NR_sigreturn | ||||
|         ALLOW_SYSCALL(sigreturn), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user