1// Copyright 2016 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7#include <object/socket_dispatcher.h>
8
9#include <string.h>
10
11#include <assert.h>
12#include <err.h>
13#include <pow2.h>
14#include <trace.h>
15
16#include <lib/user_copy/user_ptr.h>
17
18#include <vm/vm_aspace.h>
19#include <vm/vm_object.h>
20#include <vm/vm_object_paged.h>
21#include <object/handle.h>
22
23#include <zircon/rights.h>
24#include <fbl/alloc_checker.h>
25#include <fbl/auto_lock.h>
26
27#define LOCAL_TRACE 0
28
29// static
30zx_status_t SocketDispatcher::Create(uint32_t flags,
31                                     fbl::RefPtr<Dispatcher>* dispatcher0,
32                                     fbl::RefPtr<Dispatcher>* dispatcher1,
33                                     zx_rights_t* rights) {
34    LTRACE_ENTRY;
35
36    if (flags & ~ZX_SOCKET_CREATE_MASK)
37        return ZX_ERR_INVALID_ARGS;
38
39    fbl::AllocChecker ac;
40
41    zx_signals_t starting_signals = ZX_SOCKET_WRITABLE;
42
43    if (flags & ZX_SOCKET_HAS_ACCEPT)
44        starting_signals |= ZX_SOCKET_SHARE;
45
46    fbl::unique_ptr<ControlMsg> control0;
47    fbl::unique_ptr<ControlMsg> control1;
48
49    // TODO: use mbufs to avoid pinning control buffer memory.
50    if (flags & ZX_SOCKET_HAS_CONTROL) {
51        starting_signals |= ZX_SOCKET_CONTROL_WRITABLE;
52
53        control0.reset(new (&ac) ControlMsg());
54        if (!ac.check())
55            return ZX_ERR_NO_MEMORY;
56
57        control1.reset(new (&ac) ControlMsg());
58        if (!ac.check())
59            return ZX_ERR_NO_MEMORY;
60    }
61
62    auto holder0 = fbl::AdoptRef(new (&ac) PeerHolder<SocketDispatcher>());
63    if (!ac.check())
64        return ZX_ERR_NO_MEMORY;
65    auto holder1 = holder0;
66
67    auto socket0 = fbl::AdoptRef(new (&ac) SocketDispatcher(fbl::move(holder0), starting_signals,
68                                                            flags, fbl::move(control0)));
69    if (!ac.check())
70        return ZX_ERR_NO_MEMORY;
71
72    auto socket1 = fbl::AdoptRef(new (&ac) SocketDispatcher(fbl::move(holder1), starting_signals,
73                                                            flags, fbl::move(control1)));
74    if (!ac.check())
75        return ZX_ERR_NO_MEMORY;
76
77    socket0->Init(socket1);
78    socket1->Init(socket0);
79
80    *rights = ZX_DEFAULT_SOCKET_RIGHTS;
81    *dispatcher0 = fbl::move(socket0);
82    *dispatcher1 = fbl::move(socket1);
83    return ZX_OK;
84}
85
86SocketDispatcher::SocketDispatcher(fbl::RefPtr<PeerHolder<SocketDispatcher>> holder,
87                                   zx_signals_t starting_signals, uint32_t flags,
88                                   fbl::unique_ptr<ControlMsg> control_msg)
89    : PeeredDispatcher(fbl::move(holder), starting_signals),
90      flags_(flags),
91      control_msg_(fbl::move(control_msg)),
92      control_msg_len_(0),
93      read_threshold_(0),
94      write_threshold_(0),
95      read_disabled_(false) {
96}
97
98SocketDispatcher::~SocketDispatcher() {
99}
100
101// This is called before either SocketDispatcher is accessible from threads other than the one
102// initializing the socket, so it does not need locking.
103void SocketDispatcher::Init(fbl::RefPtr<SocketDispatcher> other) TA_NO_THREAD_SAFETY_ANALYSIS {
104    peer_ = fbl::move(other);
105    peer_koid_ = peer_->get_koid();
106}
107
108void SocketDispatcher::on_zero_handles_locked() {
109    canary_.Assert();
110}
111
112void SocketDispatcher::OnPeerZeroHandlesLocked() {
113    canary_.Assert();
114
115    UpdateStateLocked(ZX_SOCKET_WRITABLE, ZX_SOCKET_PEER_CLOSED);
116}
117
118zx_status_t SocketDispatcher::UserSignalSelfLocked(uint32_t clear_mask, uint32_t set_mask) {
119    canary_.Assert();
120    UpdateStateLocked(clear_mask, set_mask);
121    return ZX_OK;
122}
123
124zx_status_t SocketDispatcher::Shutdown(uint32_t how) TA_NO_THREAD_SAFETY_ANALYSIS {
125    canary_.Assert();
126
127    LTRACE_ENTRY;
128
129    const bool shutdown_read = how & ZX_SOCKET_SHUTDOWN_READ;
130    const bool shutdown_write = how & ZX_SOCKET_SHUTDOWN_WRITE;
131
132    Guard<fbl::Mutex> guard{get_lock()};
133
134    zx_signals_t signals = GetSignalsStateLocked();
135    // If we're already shut down in the requested way, return immediately.
136    const uint32_t want_signals =
137        (shutdown_read ? ZX_SOCKET_READ_DISABLED : 0) |
138        (shutdown_write ? ZX_SOCKET_WRITE_DISABLED : 0);
139    const uint32_t have_signals = signals & (ZX_SOCKET_READ_DISABLED | ZX_SOCKET_WRITE_DISABLED);
140    if (want_signals == have_signals) {
141        return ZX_OK;
142    }
143    zx_signals_t clear_mask = 0u;
144    zx_signals_t set_mask = 0u;
145    if (shutdown_read) {
146        read_disabled_ = true;
147        if (is_empty())
148            set_mask |= ZX_SOCKET_READ_DISABLED;
149    }
150    if (shutdown_write) {
151        clear_mask |= ZX_SOCKET_WRITABLE;
152        set_mask |= ZX_SOCKET_WRITE_DISABLED;
153    }
154    UpdateStateLocked(clear_mask, set_mask);
155
156    // Our peer already be closed - if so, we've already updated our own bits so we are done. If the
157    // peer is done, we need to notify them of the state change.
158    if (peer_ != nullptr) {
159        return peer_->ShutdownOtherLocked(how);
160    } else {
161        return ZX_OK;
162    }
163}
164
165zx_status_t SocketDispatcher::ShutdownOtherLocked(uint32_t how) {
166    canary_.Assert();
167
168    const bool shutdown_read = how & ZX_SOCKET_SHUTDOWN_READ;
169    const bool shutdown_write = how & ZX_SOCKET_SHUTDOWN_WRITE;
170
171    zx_signals_t clear_mask = 0u;
172    zx_signals_t set_mask = 0u;
173    if (shutdown_read) {
174        // If the other end shut down reading, we can't write any more.
175        clear_mask |= ZX_SOCKET_WRITABLE;
176        set_mask |= ZX_SOCKET_WRITE_DISABLED;
177    }
178    if (shutdown_write) {
179        // If the other end shut down writing, we can't read any more than already exists in the
180        // buffer. If we're empty, set ZX_SOCKET_READ_DISABLED now. If we aren't empty, Read() will
181        // set this bit after reading the remaining data from the socket.
182        read_disabled_ = true;
183        if (is_empty())
184            set_mask |= ZX_SOCKET_READ_DISABLED;
185    }
186
187    UpdateStateLocked(clear_mask, set_mask);
188    return ZX_OK;
189}
190
191zx_status_t SocketDispatcher::Write(user_in_ptr<const void> src, size_t len,
192                                    size_t* nwritten) TA_NO_THREAD_SAFETY_ANALYSIS {
193    canary_.Assert();
194
195    LTRACE_ENTRY;
196
197    Guard<fbl::Mutex> guard{get_lock()};
198
199    if (!peer_)
200        return ZX_ERR_PEER_CLOSED;
201    zx_signals_t signals = GetSignalsStateLocked();
202    if (signals & ZX_SOCKET_WRITE_DISABLED)
203        return ZX_ERR_BAD_STATE;
204
205    if (len == 0) {
206        *nwritten = 0;
207        return ZX_OK;
208    }
209    if (len != static_cast<size_t>(static_cast<uint32_t>(len)))
210        return ZX_ERR_INVALID_ARGS;
211
212    return peer_->WriteSelfLocked(src, len, nwritten);
213}
214
215zx_status_t SocketDispatcher::WriteControl(user_in_ptr<const void> src, size_t len)
216    TA_NO_THREAD_SAFETY_ANALYSIS {
217    canary_.Assert();
218
219    if ((flags_ & ZX_SOCKET_HAS_CONTROL) == 0)
220        return ZX_ERR_BAD_STATE;
221
222    if (len == 0)
223        return ZX_ERR_INVALID_ARGS;
224
225    if (len > ControlMsg::kSize)
226        return ZX_ERR_OUT_OF_RANGE;
227
228    Guard<fbl::Mutex> guard{get_lock()};
229    if (!peer_)
230        return ZX_ERR_PEER_CLOSED;
231
232    return peer_->WriteControlSelfLocked(src, len);
233}
234
235zx_status_t SocketDispatcher::WriteControlSelfLocked(user_in_ptr<const void> src,
236                                                     size_t len) TA_NO_THREAD_SAFETY_ANALYSIS {
237    canary_.Assert();
238
239    if (control_msg_len_ != 0)
240        return ZX_ERR_SHOULD_WAIT;
241
242    if (src.copy_array_from_user(&control_msg_->msg, len) != ZX_OK)
243        return ZX_ERR_INVALID_ARGS; // Bad user buffer.
244
245    control_msg_len_ = static_cast<uint32_t>(len);
246
247    UpdateStateLocked(0u, ZX_SOCKET_CONTROL_READABLE);
248    if (peer_)
249        peer_->UpdateStateLocked(ZX_SOCKET_CONTROL_WRITABLE, 0u);
250
251    return ZX_OK;
252}
253
254zx_status_t SocketDispatcher::WriteSelfLocked(user_in_ptr<const void> src, size_t len,
255                                              size_t* written) TA_NO_THREAD_SAFETY_ANALYSIS {
256    canary_.Assert();
257
258    if (is_full())
259        return ZX_ERR_SHOULD_WAIT;
260
261    bool was_empty = is_empty();
262
263    size_t st = 0u;
264    zx_status_t status;
265    if (flags_ & ZX_SOCKET_DATAGRAM) {
266        status = data_.WriteDatagram(src, len, &st);
267    } else {
268        status = data_.WriteStream(src, len, &st);
269    }
270    if (status)
271        return status;
272
273    zx_signals_t clear = 0u;
274    zx_signals_t set = 0u;
275
276    if (st > 0) {
277        if (was_empty)
278            set |= ZX_SOCKET_READABLE;
279        // Assert signal if we go above the read threshold
280        if ((read_threshold_ > 0) && (data_.size() >= read_threshold_))
281            set |= ZX_SOCKET_READ_THRESHOLD;
282        if (set) {
283            UpdateStateLocked(0u, set);
284        }
285        if (peer_) {
286            size_t peer_write_threshold = peer_->write_threshold_;
287            // If free space falls below threshold, de-signal
288            if ((peer_write_threshold > 0) &&
289                ((data_.max_size() - data_.size()) < peer_write_threshold))
290                clear |= ZX_SOCKET_WRITE_THRESHOLD;
291        }
292    }
293
294    if (peer_ && is_full())
295        clear |= ZX_SOCKET_WRITABLE;
296
297    if (clear)
298        peer_->UpdateStateLocked(clear, 0u);
299
300    *written = st;
301    return status;
302}
303
304zx_status_t SocketDispatcher::Read(user_out_ptr<void> dst, size_t len,
305                                   size_t* nread) TA_NO_THREAD_SAFETY_ANALYSIS {
306    canary_.Assert();
307
308    LTRACE_ENTRY;
309
310    Guard<fbl::Mutex> guard{get_lock()};
311
312    // Just query for bytes outstanding.
313    if (!dst && len == 0) {
314        *nread = data_.size();
315        return ZX_OK;
316    }
317
318    if (len != (size_t)((uint32_t)len))
319        return ZX_ERR_INVALID_ARGS;
320
321    if (is_empty()) {
322        if (!peer_)
323            return ZX_ERR_PEER_CLOSED;
324        // If reading is disabled on our end and we're empty, we'll never become readable again.
325        // Return a different error to let the caller know.
326        if (read_disabled_)
327            return ZX_ERR_BAD_STATE;
328        return ZX_ERR_SHOULD_WAIT;
329    }
330
331    bool was_full = is_full();
332
333    auto st = data_.Read(dst, len, flags_ & ZX_SOCKET_DATAGRAM);
334
335    zx_signals_t clear = 0u;
336    zx_signals_t set = 0u;
337
338    // Deassert signal if we fell below the read threshold
339    if ((read_threshold_ > 0) && (data_.size() < read_threshold_))
340        clear |= ZX_SOCKET_READ_THRESHOLD;
341
342    if (is_empty()) {
343        if (read_disabled_)
344            set |= ZX_SOCKET_READ_DISABLED;
345        clear |= ZX_SOCKET_READABLE;
346    }
347    if (set || clear) {
348        UpdateStateLocked(clear, set);
349        clear = set = 0u;
350    }
351    if (peer_) {
352        // Assert (write threshold) signal if space available is above
353        // threshold.
354        size_t peer_write_threshold = peer_->write_threshold_;
355        if (peer_write_threshold > 0 &&
356            ((data_.max_size() - data_.size()) >= peer_write_threshold))
357            set |= ZX_SOCKET_WRITE_THRESHOLD;
358        if (was_full && (st > 0))
359            set |= ZX_SOCKET_WRITABLE;
360        if (set)
361            peer_->UpdateStateLocked(0u, set);
362    }
363
364    *nread = static_cast<size_t>(st);
365    return ZX_OK;
366}
367
368zx_status_t SocketDispatcher::ReadControl(user_out_ptr<void> dst, size_t len,
369                                          size_t* nread) TA_NO_THREAD_SAFETY_ANALYSIS {
370    canary_.Assert();
371
372    if ((flags_ & ZX_SOCKET_HAS_CONTROL) == 0) {
373        return ZX_ERR_BAD_STATE;
374    }
375
376    Guard<fbl::Mutex> guard{get_lock()};
377
378    if (control_msg_len_ == 0)
379        return ZX_ERR_SHOULD_WAIT;
380
381    size_t copy_len = MIN(control_msg_len_, len);
382    if (dst.copy_array_to_user(&control_msg_->msg, copy_len) != ZX_OK)
383        return ZX_ERR_INVALID_ARGS; // Invalid user buffer.
384
385    control_msg_len_ = 0;
386    UpdateStateLocked(ZX_SOCKET_CONTROL_READABLE, 0u);
387    if (peer_)
388        peer_->UpdateStateLocked(0u, ZX_SOCKET_CONTROL_WRITABLE);
389
390    *nread = copy_len;
391    return ZX_OK;
392}
393
394zx_status_t SocketDispatcher::CheckShareable(SocketDispatcher* to_send) {
395    // We disallow sharing of sockets that support sharing themselves
396    // and disallow sharing either end of the socket we're going to
397    // share on, thus preventing loops, etc.
398    Guard<fbl::Mutex> guard{get_lock()};
399    if ((to_send->flags_ & ZX_SOCKET_HAS_ACCEPT) ||
400        (to_send == this) || (to_send == peer_.get()))
401        return ZX_ERR_BAD_STATE;
402    return ZX_OK;
403}
404
405zx_status_t SocketDispatcher::Share(HandleOwner h) TA_NO_THREAD_SAFETY_ANALYSIS {
406    canary_.Assert();
407
408    LTRACE_ENTRY;
409
410    if (!(flags_ & ZX_SOCKET_HAS_ACCEPT))
411        return ZX_ERR_NOT_SUPPORTED;
412
413    Guard<fbl::Mutex> guard{get_lock()};
414    if (!peer_)
415        return ZX_ERR_PEER_CLOSED;
416
417    return peer_->ShareSelfLocked(fbl::move(h));
418}
419
420zx_status_t SocketDispatcher::ShareSelfLocked(HandleOwner h) TA_NO_THREAD_SAFETY_ANALYSIS {
421    canary_.Assert();
422
423    if (accept_queue_)
424        return ZX_ERR_SHOULD_WAIT;
425
426    accept_queue_ = fbl::move(h);
427
428    UpdateStateLocked(0, ZX_SOCKET_ACCEPT);
429    if (peer_)
430        peer_->UpdateStateLocked(ZX_SOCKET_SHARE, 0);
431
432    return ZX_OK;
433}
434
435zx_status_t SocketDispatcher::Accept(HandleOwner* h) TA_NO_THREAD_SAFETY_ANALYSIS {
436    canary_.Assert();
437
438    if (!(flags_ & ZX_SOCKET_HAS_ACCEPT))
439        return ZX_ERR_NOT_SUPPORTED;
440
441    Guard<fbl::Mutex> guard{get_lock()};
442
443    if (!accept_queue_)
444        return ZX_ERR_SHOULD_WAIT;
445
446    *h = fbl::move(accept_queue_);
447
448    UpdateStateLocked(ZX_SOCKET_ACCEPT, 0);
449    if (peer_)
450        peer_->UpdateStateLocked(0, ZX_SOCKET_SHARE);
451
452    return ZX_OK;
453}
454
455size_t SocketDispatcher::ReceiveBufferMax() const {
456    canary_.Assert();
457    Guard<fbl::Mutex> guard{get_lock()};
458    return data_.max_size();
459}
460
461size_t SocketDispatcher::ReceiveBufferSize() const {
462    canary_.Assert();
463    Guard<fbl::Mutex> guard{get_lock()};
464    return data_.size();
465}
466
467// NOTE(abdulla): peer_ is protected by get_lock() while peer_->data_
468// is protected by peer_->get_lock(). These two locks are aliases of
469// one another so must only acquire one of them. Thread-safety
470// analysis does not know they are the same lock so we must disable
471// analysis.
472size_t SocketDispatcher::TransmitBufferMax() const TA_NO_THREAD_SAFETY_ANALYSIS {
473    canary_.Assert();
474    Guard<fbl::Mutex> guard{get_lock()};
475    return peer_ ? peer_->data_.max_size() : 0;
476}
477
478size_t SocketDispatcher::TransmitBufferSize() const TA_NO_THREAD_SAFETY_ANALYSIS {
479    canary_.Assert();
480    Guard<fbl::Mutex> guard{get_lock()};
481    return peer_ ? peer_->data_.size() : 0;
482}
483
484void SocketDispatcher::GetInfo(zx_info_socket_t* info) const TA_NO_THREAD_SAFETY_ANALYSIS {
485    canary_.Assert();
486    Guard<fbl::Mutex> guard{get_lock()};
487    *info = zx_info_socket_t{
488        .options = flags_,
489        .rx_buf_max = data_.max_size(),
490        .rx_buf_size = data_.size(),
491        .tx_buf_max = peer_ ? peer_->data_.max_size() : 0,
492        .tx_buf_size = peer_ ? peer_->data_.size() : 0,
493    };
494}
495
496size_t SocketDispatcher::GetReadThreshold() const TA_NO_THREAD_SAFETY_ANALYSIS {
497    canary_.Assert();
498    Guard<fbl::Mutex> guard{get_lock()};
499    return read_threshold_;
500}
501
502size_t SocketDispatcher::GetWriteThreshold() const TA_NO_THREAD_SAFETY_ANALYSIS {
503    canary_.Assert();
504    Guard<fbl::Mutex> guard{get_lock()};
505    return write_threshold_;
506}
507
508zx_status_t SocketDispatcher::SetReadThreshold(size_t value) TA_NO_THREAD_SAFETY_ANALYSIS {
509    canary_.Assert();
510    Guard<fbl::Mutex> guard{get_lock()};
511    if (value > data_.max_size())
512        return ZX_ERR_INVALID_ARGS;
513    read_threshold_ = value;
514    // Setting 0 disables thresholding. Deassert signal unconditionally.
515    if (value == 0) {
516        UpdateStateLocked(ZX_SOCKET_READ_THRESHOLD, 0u);
517    } else {
518        // Assert signal if we have queued data above the read threshold
519        if (data_.size() >= read_threshold_)
520            UpdateStateLocked(0u, ZX_SOCKET_READ_THRESHOLD);
521    }
522    return ZX_OK;
523}
524
525zx_status_t SocketDispatcher::SetWriteThreshold(size_t value) TA_NO_THREAD_SAFETY_ANALYSIS {
526    canary_.Assert();
527    Guard<fbl::Mutex> guard{get_lock()};
528    size_t tx_buffer_max;
529    tx_buffer_max = peer_ ? peer_->data_.max_size() : 0;
530    if (value > tx_buffer_max)
531        return ZX_ERR_INVALID_ARGS;
532    write_threshold_ = value;
533    // Setting 0 disables thresholding. Deassert signal unconditionally.
534    if (value == 0) {
535        UpdateStateLocked(ZX_SOCKET_WRITE_THRESHOLD, 0u);
536    } else {
537        // Assert signal if we have available space above the write threshold
538        if (peer_ &&
539            (peer_->data_.max_size() - peer_->data_.size()) >= write_threshold_)
540            UpdateStateLocked(0u, ZX_SOCKET_WRITE_THRESHOLD);
541    }
542    return ZX_OK;
543}
544