Skip to content

Commit 796dc3c

Browse files
committed
fix(process): gate platform socket options
1 parent dee6d49 commit 796dc3c

2 files changed

Lines changed: 98 additions & 23 deletions

File tree

neovm-core/src/emacs_core/process.rs

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,12 +2111,14 @@ fn process_contact_server_p(proc: &Process) -> bool {
21112111

21122112
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
21132113
enum NetworkSocketOption {
2114+
#[cfg(any(target_os = "linux", target_os = "android"))]
21142115
Bindtodevice,
21152116
Broadcast,
21162117
Dontroute,
21172118
Keepalive,
21182119
Linger,
21192120
Oobinline,
2121+
#[cfg(any(target_os = "linux", target_os = "android"))]
21202122
Priority,
21212123
Reuseaddr,
21222124
Nodelay,
@@ -2163,12 +2165,14 @@ enum PendingNetworkConnectCompletion {
21632165
impl NetworkSocketOption {
21642166
fn from_keyword(keyword: ProcessKeyword) -> Option<Self> {
21652167
match keyword {
2168+
#[cfg(any(target_os = "linux", target_os = "android"))]
21662169
ProcessKeyword::Bindtodevice => Some(Self::Bindtodevice),
21672170
ProcessKeyword::Broadcast => Some(Self::Broadcast),
21682171
ProcessKeyword::Dontroute => Some(Self::Dontroute),
21692172
ProcessKeyword::Keepalive => Some(Self::Keepalive),
21702173
ProcessKeyword::Linger => Some(Self::Linger),
21712174
ProcessKeyword::Oobinline => Some(Self::Oobinline),
2175+
#[cfg(any(target_os = "linux", target_os = "android"))]
21722176
ProcessKeyword::Priority => Some(Self::Priority),
21732177
ProcessKeyword::Reuseaddr => Some(Self::Reuseaddr),
21742178
ProcessKeyword::Nodelay => Some(Self::Nodelay),
@@ -2290,7 +2294,7 @@ fn set_socket_linger_option_raw(fd: RawFd, value: Value) -> std::io::Result<()>
22902294
setsockopt_raw(fd, libc::SOL_SOCKET, libc::SO_LINGER, &raw)
22912295
}
22922296

2293-
#[cfg(unix)]
2297+
#[cfg(any(target_os = "linux", target_os = "android"))]
22942298
fn set_socket_priority_option_raw(fd: RawFd, priority: i32) -> std::io::Result<()> {
22952299
let raw = priority as libc::c_int;
22962300
setsockopt_raw(fd, libc::SOL_SOCKET, libc::SO_PRIORITY, &raw)
@@ -2303,6 +2307,7 @@ fn apply_network_socket_option_to_socket(
23032307
) -> EvalResult {
23042308
let value = spec.value;
23052309
let result = match spec.option {
2310+
#[cfg(any(target_os = "linux", target_os = "android"))]
23062311
NetworkSocketOption::Bindtodevice => {
23072312
if value.is_nil() {
23082313
socket.bind_device(None)
@@ -2319,6 +2324,7 @@ fn apply_network_socket_option_to_socket(
23192324
NetworkSocketOption::Keepalive => socket.set_keepalive(value.is_truthy()),
23202325
NetworkSocketOption::Linger => set_socket_linger_option_raw(socket.as_raw_fd(), value),
23212326
NetworkSocketOption::Oobinline => socket.set_out_of_band_inline(value.is_truthy()),
2327+
#[cfg(any(target_os = "linux", target_os = "android"))]
23222328
NetworkSocketOption::Priority => {
23232329
let priority = network_option_i32_value(spec.keyword, value)?;
23242330
set_socket_priority_option_raw(socket.as_raw_fd(), priority)
@@ -2549,14 +2555,31 @@ fn udp_unspecified_addr_for(remote: SocketAddr) -> SocketAddr {
25492555
}
25502556

25512557
fn datagram_zero_address_for(addr: SocketAddr) -> Value {
2552-
let family_len = std::mem::size_of::<libc::sa_family_t>();
25532558
let raw_len = match addr {
2554-
SocketAddr::V4(_) => std::mem::size_of::<libc::sockaddr_in>() - family_len,
2555-
SocketAddr::V6(_) => std::mem::size_of::<libc::sockaddr_in6>() - family_len,
2559+
SocketAddr::V4(_) => socket_addr_payload_len_v4(),
2560+
SocketAddr::V6(_) => socket_addr_payload_len_v6(),
25562561
};
25572562
Value::cons(Value::fixnum(0), int_vector(&vec![0_i64; raw_len]))
25582563
}
25592564

2565+
fn socket_addr_payload_len_v4() -> usize {
2566+
cfg_select! {
2567+
unix => {
2568+
std::mem::size_of::<libc::sockaddr_in>() - std::mem::size_of::<libc::sa_family_t>()
2569+
}
2570+
_ => { 14 }
2571+
}
2572+
}
2573+
2574+
fn socket_addr_payload_len_v6() -> usize {
2575+
cfg_select! {
2576+
unix => {
2577+
std::mem::size_of::<libc::sockaddr_in6>() - std::mem::size_of::<libc::sa_family_t>()
2578+
}
2579+
_ => { 26 }
2580+
}
2581+
}
2582+
25602583
#[cfg(unix)]
25612584
fn datagram_zero_unix_address() -> Value {
25622585
let raw_len =
@@ -3974,12 +3997,12 @@ impl ProcessManager {
39743997
pub fn kill_process(&mut self, id: ProcessId) -> bool {
39753998
if let Some(proc) = self.processes.get_mut(&id) {
39763999
Self::unregister_process_poll_sources(self.wait_backend.poller(), proc);
3977-
kill_real_process_child(proc, libc::SIGKILL);
4000+
kill_real_process_child(proc, signal_kill_number());
39784001
proc.tls_stream.take();
39794002
proc.gnutls_initstage = GnutlsInitStage::Empty;
39804003
proc.gnutls_boot_parameters = Value::NIL;
39814004
proc.network_socket.take();
3982-
proc.status = process_status_signal_value(9);
4005+
proc.status = process_status_signal_value(signal_kill_number());
39834006
true
39844007
} else {
39854008
false
@@ -4000,8 +4023,8 @@ impl ProcessManager {
40004023
} else if proc.status_notify_pending && !proc.pending_terminal_status.is_nil() {
40014024
proc.status = proc.pending_terminal_status;
40024025
} else if !process_status_is_exit_or_signal(&proc.status) {
4003-
kill_real_process_child(&mut proc, libc::SIGKILL);
4004-
proc.status = process_status_signal_value(9);
4026+
kill_real_process_child(&mut proc, signal_kill_number());
4027+
proc.status = process_status_signal_value(signal_kill_number());
40054028
}
40064029
proc.status_notify_pending = false;
40074030
proc.pending_terminal_status = Value::NIL;
@@ -4032,8 +4055,8 @@ impl ProcessManager {
40324055
if proc.kind != ProcessKind::Real || process_status_is_exit_or_signal(&proc.status) {
40334056
return false;
40344057
}
4035-
kill_real_process_child(proc, libc::SIGHUP);
4036-
proc.pending_terminal_status = process_status_signal_value(libc::SIGHUP);
4058+
kill_real_process_child(proc, signal_hup_number());
4059+
proc.pending_terminal_status = process_status_signal_value(signal_hup_number());
40374060
proc.status_notify_pending = true;
40384061
true
40394062
}
@@ -6648,6 +6671,20 @@ fn kill_real_process_child(proc: &mut Process, signal_num: i32) {
66486671
}
66496672
}
66506673

6674+
fn signal_hup_number() -> i32 {
6675+
cfg_select! {
6676+
unix => { libc::SIGHUP }
6677+
_ => { 1 }
6678+
}
6679+
}
6680+
6681+
fn signal_kill_number() -> i32 {
6682+
cfg_select! {
6683+
unix => { libc::SIGKILL }
6684+
_ => { 9 }
6685+
}
6686+
}
6687+
66516688
#[cfg(unix)]
66526689
fn send_signal_to_pid(pid: i64, signal_num: i32) -> i32 {
66536690
unsafe { libc::kill(pid as libc::pid_t, signal_num) }
@@ -6695,7 +6732,9 @@ fn signal_name_number(name: &str) -> Option<i32> {
66956732
"VTALRM" => Some(libc::SIGVTALRM),
66966733
"PROF" => Some(libc::SIGPROF),
66976734
"WINCH" => Some(libc::SIGWINCH),
6735+
#[cfg(any(target_os = "linux", target_os = "android"))]
66986736
"POLL" | "IO" => Some(libc::SIGPOLL),
6737+
#[cfg(any(target_os = "linux", target_os = "android"))]
66996738
"PWR" => Some(libc::SIGPWR),
67006739
"SYS" => Some(libc::SIGSYS),
67016740
_ => realtime_signal_name_number(&name),
@@ -12174,7 +12213,7 @@ pub(crate) fn builtin_kill_process_impl(
1217412213
if proc.kind != ProcessKind::Real {
1217512214
return Err(signal_process_not_subprocess(proc));
1217612215
}
12177-
kill_real_process_child(proc, libc::SIGKILL);
12216+
kill_real_process_child(proc, signal_kill_number());
1217812217
}
1217912218
Ok(ret)
1218012219
}
@@ -12516,21 +12555,35 @@ fn process_attributes_pid_arg(value: Value) -> Result<i64, Flow> {
1251612555
let f = value.xfloat();
1251712556
if !f.is_finite()
1251812557
|| f.fract() != 0.0
12519-
|| f < libc::pid_t::MIN as f64
12520-
|| f > libc::pid_t::MAX as f64
12558+
|| f < process_id_min() as f64
12559+
|| f > process_id_max() as f64
1252112560
{
1252212561
return Err(signal_process_attributes_pid_range_error());
1252312562
}
1252412563
f as i64
1252512564
}
1252612565
_ => return Err(signal_wrong_type_numberp(value)),
1252712566
};
12528-
if pid < libc::pid_t::MIN as i64 || pid > libc::pid_t::MAX as i64 {
12567+
if pid < process_id_min() || pid > process_id_max() {
1252912568
return Err(signal_process_attributes_pid_range_error());
1253012569
}
1253112570
Ok(pid)
1253212571
}
1253312572

12573+
fn process_id_min() -> i64 {
12574+
cfg_select! {
12575+
unix => { libc::pid_t::MIN as i64 }
12576+
_ => { i32::MIN as i64 }
12577+
}
12578+
}
12579+
12580+
fn process_id_max() -> i64 {
12581+
cfg_select! {
12582+
unix => { libc::pid_t::MAX as i64 }
12583+
_ => { i32::MAX as i64 }
12584+
}
12585+
}
12586+
1253412587
/// (make-process &rest ARGS) -> process-or-nil
1253512588
pub(crate) fn builtin_make_process(
1253612589
eval: &mut super::eval::Context,
@@ -14533,24 +14586,30 @@ pub(crate) fn make_network_process_subfeatures() -> Value {
1453314586
// Advertise only behavior that this runtime actually implements. Packages
1453414587
// use `featurep' to choose code paths, so keep this list tied to backed
1453514588
// behavior, not parser acceptance.
14536-
Value::list(vec![
14589+
let mut features = vec![
1453714590
Value::keyword("nodelay"),
1453814591
Value::keyword("reuseaddr"),
14539-
Value::keyword("priority"),
1454014592
Value::keyword("oobinline"),
1454114593
Value::keyword("linger"),
1454214594
Value::keyword("keepalive"),
1454314595
Value::keyword("dontroute"),
1454414596
Value::keyword("broadcast"),
14545-
Value::keyword("bindtodevice"),
1454614597
Value::list(vec![Value::keyword("family"), Value::symbol("local")]),
1454714598
Value::list(vec![Value::keyword("family"), Value::symbol("ipv4")]),
1454814599
Value::list(vec![Value::keyword("family"), Value::symbol("ipv6")]),
1454914600
Value::list(vec![Value::keyword("service"), Value::T]),
1455014601
Value::list(vec![Value::keyword("server"), Value::T]),
1455114602
Value::list(vec![Value::keyword("nowait"), Value::T]),
1455214603
Value::list(vec![Value::keyword("type"), Value::symbol("datagram")]),
14553-
])
14604+
];
14605+
cfg_select! {
14606+
any(target_os = "linux", target_os = "android") => {
14607+
features.insert(2, Value::keyword("priority"));
14608+
features.insert(8, Value::keyword("bindtodevice"));
14609+
}
14610+
_ => {}
14611+
}
14612+
Value::list(features)
1455414613
}
1455514614

1455614615
/// (set-binary-mode STREAM MODE) -> t

neovm-core/src/emacs_core/process_test.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5340,14 +5340,28 @@ fn make_network_process_feature_advertisement_is_conservative() {
53405340
(get 'make-network-process 'subfeatures)"#,
53415341
);
53425342

5343-
assert_eq!(results[0], "OK (t t t t t t t t nil t t t t t t t t t)");
5344-
assert_eq!(
5345-
results[1],
5346-
"OK (:nodelay :reuseaddr :priority :oobinline :linger :keepalive :dontroute :broadcast :bindtodevice (:family local) (:family ipv4) (:family ipv6) (:service t) (:server t) (:nowait t) (:type datagram))"
5347-
);
5343+
let expected_featurep = cfg_select! {
5344+
any(target_os = "linux", target_os = "android") => {
5345+
"OK (t t t t t t t t nil t t t t t t t t t)"
5346+
}
5347+
_ => {
5348+
"OK (t t t t t t t t nil t t nil t nil t t t t)"
5349+
}
5350+
};
5351+
let expected_subfeatures = cfg_select! {
5352+
any(target_os = "linux", target_os = "android") => {
5353+
"OK (:nodelay :reuseaddr :priority :oobinline :linger :keepalive :dontroute :broadcast :bindtodevice (:family local) (:family ipv4) (:family ipv6) (:service t) (:server t) (:nowait t) (:type datagram))"
5354+
}
5355+
_ => {
5356+
"OK (:nodelay :reuseaddr :oobinline :linger :keepalive :dontroute :broadcast (:family local) (:family ipv4) (:family ipv6) (:service t) (:server t) (:nowait t) (:type datagram))"
5357+
}
5358+
};
5359+
assert_eq!(results[0], expected_featurep);
5360+
assert_eq!(results[1], expected_subfeatures);
53485361
}
53495362

53505363
#[test]
5364+
#[cfg(any(target_os = "linux", target_os = "android"))]
53515365
fn set_network_process_option_applies_known_options_and_updates_contact_like_gnu() {
53525366
crate::test_utils::init_test_tracing();
53535367
let results = eval_all(
@@ -5373,6 +5387,7 @@ fn set_network_process_option_applies_known_options_and_updates_contact_like_gnu
53735387
}
53745388

53755389
#[test]
5390+
#[cfg(any(target_os = "linux", target_os = "android"))]
53765391
fn make_network_process_constructor_socket_options_are_applied_like_gnu() {
53775392
crate::test_utils::init_test_tracing();
53785393
let results = eval_all(
@@ -5399,6 +5414,7 @@ fn make_network_process_constructor_socket_options_are_applied_like_gnu() {
53995414
}
54005415

54015416
#[test]
5417+
#[cfg(any(target_os = "linux", target_os = "android"))]
54025418
fn set_network_process_option_rejects_bad_values_like_gnu() {
54035419
crate::test_utils::init_test_tracing();
54045420
let results = eval_all(

0 commit comments

Comments
 (0)