Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impl GetSockOpt for nix::sys::socket::sockopt::SockType causes UB with unknown socket type #1819

Closed
ahcodedthat opened this issue Sep 15, 2022 · 1 comment · Fixed by #1821
Assignees
Labels

Comments

@ahcodedthat
Copy link

Description

I noticed that the implementation of GetSockOpt for nix::sys::socket::sockopt::SockType simply assumes that the socket type returned by the kernel is one of those defined in enum nix::sys::socket::SockType without checking. If that assumption is violated, you get undefined behavior.

Linux has at least one such socket type already (SOCK_PACKET), and operating systems are free to add new ones at any time.

Other socket options probably suffer from a similar problem, but I haven't tested that.

Alternative

socket2::Type deals with this problem by being a newtype wrapper around a c_int instead of an enum.

Proof of concept

This works on Linux only.

use nix::sys::socket::{getsockopt, sockopt};
use std::process::ExitCode;

fn main() -> ExitCode {
	let sockfd = unsafe { libc::socket(libc::AF_PACKET, libc::SOCK_PACKET, 0) };

	if sockfd == -1 {
		eprintln!("Error opening socket: {}", nix::Error::last());
		return ExitCode::FAILURE;
	}

	let socktype = match getsockopt(sockfd, sockopt::SockType) {
		Ok(ok) => ok,
		Err(error) => {
			eprintln!("Error getting socket type: {error}");
			return ExitCode::FAILURE
		}
	};

	eprintln!("The socket's type is: {socktype:?}");
	ExitCode::SUCCESS
}

Output:

$ target/debug/nix-ub 
The socket's type is: Segmentation fault

Note that creating a SOCK_PACKET socket is a privileged operation, so the executable needs to be granted that privilege first:

$ cargo build
$ sudo setcap CAP_NET_RAW+eip target/debug/nix-ub
@asomers asomers added the A-bug label Sep 15, 2022
@asomers asomers self-assigned this Sep 15, 2022
@asomers
Copy link
Member

asomers commented Sep 15, 2022

Good catch.

asomers added a commit to asomers/nix that referenced this issue Sep 17, 2022
When reading a value into an enum from getsockopt, we must validate it.
Failing to do so can lead to UB for example with SOCK_PACKET on Linux.

Perform the validation in GetSockOpt::get.  Currently SockType is the
only type that requires validation.

Fixes nix-rust#1819
asomers added a commit to asomers/nix that referenced this issue Sep 17, 2022
When reading a value into an enum from getsockopt, we must validate it.
Failing to do so can lead to UB for example with SOCK_PACKET on Linux.

Perform the validation in GetSockOpt::get.  Currently SockType is the
only type that requires validation.

Fixes nix-rust#1819
asomers added a commit to asomers/nix that referenced this issue Sep 17, 2022
When reading a value into an enum from getsockopt, we must validate it.
Failing to do so can lead to UB for example with SOCK_PACKET on Linux.

Perform the validation in GetSockOpt::get.  Currently SockType is the
only type that requires validation.

Fixes nix-rust#1819
bors bot added a commit that referenced this issue Nov 29, 2022
1821: Fix UB in the SO_TYPE sockopt r=rtzoeller a=asomers

When reading a value into an enum from getsockopt, we must validate it. Failing to do so can lead to UB for example with SOCK_PACKET on Linux.

Perform the validation in GetSockOpt::get.  Currently SockType is the only type that requires validation.

Fixes #1819

Co-authored-by: Alan Somers <asomers@gmail.com>
@bors bors bot closed this as completed in 8e91b28 Nov 29, 2022
rtzoeller pushed a commit to rtzoeller/nix that referenced this issue Dec 2, 2022
When reading a value into an enum from getsockopt, we must validate it.
Failing to do so can lead to UB for example with SOCK_PACKET on Linux.

Perform the validation in GetSockOpt::get.  Currently SockType is the
only type that requires validation.

Fixes nix-rust#1819
rtzoeller pushed a commit to rtzoeller/nix that referenced this issue Dec 2, 2022
When reading a value into an enum from getsockopt, we must validate it.
Failing to do so can lead to UB for example with SOCK_PACKET on Linux.

Perform the validation in GetSockOpt::get.  Currently SockType is the
only type that requires validation.

Fixes nix-rust#1819
rtzoeller pushed a commit to rtzoeller/nix that referenced this issue Dec 2, 2022
When reading a value into an enum from getsockopt, we must validate it.
Failing to do so can lead to UB for example with SOCK_PACKET on Linux.

Perform the validation in GetSockOpt::get.  Currently SockType is the
only type that requires validation.

Fixes nix-rust#1819
rtzoeller pushed a commit to rtzoeller/nix that referenced this issue Dec 2, 2022
When reading a value into an enum from getsockopt, we must validate it.
Failing to do so can lead to UB for example with SOCK_PACKET on Linux.

Perform the validation in GetSockOpt::get.  Currently SockType is the
only type that requires validation.

Fixes nix-rust#1819
rtzoeller pushed a commit to rtzoeller/nix that referenced this issue Dec 2, 2022
When reading a value into an enum from getsockopt, we must validate it.
Failing to do so can lead to UB for example with SOCK_PACKET on Linux.

Perform the validation in GetSockOpt::get.  Currently SockType is the
only type that requires validation.

Fixes nix-rust#1819
rtzoeller pushed a commit to rtzoeller/nix that referenced this issue Dec 2, 2022
When reading a value into an enum from getsockopt, we must validate it.
Failing to do so can lead to UB for example with SOCK_PACKET on Linux.

Perform the validation in GetSockOpt::get.  Currently SockType is the
only type that requires validation.

Fixes nix-rust#1819
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants