summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/socket/control
diff options
context:
space:
mode:
authorDean Deng <deandeng@google.com>2019-12-10 19:14:05 -0800
committergVisor bot <gvisor-bot@google.com>2019-12-10 19:27:42 -0800
commit2e3b9b0a68d8f191d061008feda6e4a4ce202a78 (patch)
tree856007f4e14500289ff970236d46d3964799e9ee /pkg/sentry/socket/control
parent46651a7d26559bdc69d460bdeb4de5968212d615 (diff)
Deduplicate and simplify control message processing for recvmsg and sendmsg.
Also, improve performance by calculating how much space is needed before making an allocation for sendmsg in hostinet. PiperOrigin-RevId: 284898581
Diffstat (limited to 'pkg/sentry/socket/control')
-rw-r--r--pkg/sentry/socket/control/control.go51
1 files changed, 35 insertions, 16 deletions
diff --git a/pkg/sentry/socket/control/control.go b/pkg/sentry/socket/control/control.go
index fa3188d51..af1a4e95f 100644
--- a/pkg/sentry/socket/control/control.go
+++ b/pkg/sentry/socket/control/control.go
@@ -348,43 +348,62 @@ func PackTClass(t *kernel.Task, tClass int32, buf []byte) []byte {
)
}
-func addSpaceForCmsg(cmsgDataLen int, buf []byte) []byte {
- newBuf := make([]byte, 0, len(buf)+linux.SizeOfControlMessageHeader+cmsgDataLen)
- return append(newBuf, buf...)
-}
-
-// PackControlMessages converts the given ControlMessages struct into a buffer.
+// PackControlMessages packs control messages into the given buffer.
+//
// We skip control messages specific to Unix domain sockets.
-func PackControlMessages(t *kernel.Task, cmsgs socket.ControlMessages) []byte {
- var buf []byte
- // The use of t.Arch().Width() is analogous to Linux's use of sizeof(long) in
- // CMSG_ALIGN.
- width := t.Arch().Width()
-
+//
+// Note that some control messages may be truncated if they do not fit under
+// the capacity of buf.
+func PackControlMessages(t *kernel.Task, cmsgs socket.ControlMessages, buf []byte) []byte {
if cmsgs.IP.HasTimestamp {
- buf = addSpaceForCmsg(int(width), buf)
buf = PackTimestamp(t, cmsgs.IP.Timestamp, buf)
}
if cmsgs.IP.HasInq {
// In Linux, TCP_CM_INQ is added after SO_TIMESTAMP.
- buf = addSpaceForCmsg(AlignUp(linux.SizeOfControlMessageInq, width), buf)
buf = PackInq(t, cmsgs.IP.Inq, buf)
}
if cmsgs.IP.HasTOS {
- buf = addSpaceForCmsg(AlignUp(linux.SizeOfControlMessageTOS, width), buf)
buf = PackTOS(t, cmsgs.IP.TOS, buf)
}
if cmsgs.IP.HasTClass {
- buf = addSpaceForCmsg(AlignUp(linux.SizeOfControlMessageTClass, width), buf)
buf = PackTClass(t, cmsgs.IP.TClass, buf)
}
return buf
}
+// cmsgSpace is equivalent to CMSG_SPACE in Linux.
+func cmsgSpace(t *kernel.Task, dataLen int) int {
+ return linux.SizeOfControlMessageHeader + AlignUp(dataLen, t.Arch().Width())
+}
+
+// CmsgsSpace returns the number of bytes needed to fit the control messages
+// represented in cmsgs.
+func CmsgsSpace(t *kernel.Task, cmsgs socket.ControlMessages) int {
+ space := 0
+
+ if cmsgs.IP.HasTimestamp {
+ space += cmsgSpace(t, linux.SizeOfTimeval)
+ }
+
+ if cmsgs.IP.HasInq {
+ space += cmsgSpace(t, linux.SizeOfControlMessageInq)
+ }
+
+ if cmsgs.IP.HasTOS {
+ space += cmsgSpace(t, linux.SizeOfControlMessageTOS)
+ }
+
+ if cmsgs.IP.HasTClass {
+ space += cmsgSpace(t, linux.SizeOfControlMessageTClass)
+ }
+
+ return space
+}
+
// Parse parses a raw socket control message into portable objects.
func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte) (socket.ControlMessages, error) {
var (