func main() { sk := nlgo.NlSocketAlloc() if err := nlgo.GenlConnect(sk); err != nil { panic(err) } else if err := nlgo.GenlSendSimple(sk, nlgo.GENL_ID_CTRL, nlgo.CTRL_CMD_GETFAMILY, nlgo.CTRL_VERSION, syscall.NLM_F_DUMP); err != nil { panic(err) } nl80211 := nlgo.NlSocketAlloc() if err := nlgo.GenlConnect(nl80211); err != nil { panic(err) } data := make([]byte, syscall.Getpagesize()) if n, _, _, _, err := syscall.Recvmsg(sk.Fd, data, nil, 0); err != nil { panic(err) } else if msgs, err := syscall.ParseNetlinkMessage(data[:n]); err != nil { log.Print("X", err) } else { for _, msg := range msgs { genl := *(*nlgo.GenlMsghdr)(unsafe.Pointer(&msg.Data[0])) if msg.Header.Type == nlgo.GENL_ID_CTRL && genl.Cmd == nlgo.CTRL_CMD_NEWFAMILY { if attr, err := nlgo.CtrlPolicy.Parse(msg.Data[nlgo.GENL_HDRLEN:]); err != nil { log.Print(err) } else if amap, ok := attr.(nlgo.AttrMap); !ok { log.Print(attr) } else if value := amap.Get(nlgo.CTRL_ATTR_FAMILY_NAME).(nlgo.NulString); string(value) == "nl80211" { log.Printf("%v", attr) for _, g := range amap.Get(nlgo.CTRL_ATTR_MCAST_GROUPS).(nlgo.AttrSlice).Slice() { group := g.Value.(nlgo.AttrMap) pid := group.Get(nlgo.CTRL_ATTR_MCAST_GRP_ID).(nlgo.U32) if err := nlgo.NlSocketAddMembership(nl80211, int(pid)); err != nil { log.Print(err) } } } } else { log.Print("UNKNOWN") } } } nlgo.NlSocketFree(sk) for { if n, _, _, _, err := syscall.Recvmsg(nl80211.Fd, data, nil, 0); err != nil { panic(err) } else if msgs, err := syscall.ParseNetlinkMessage(data[:n]); err != nil { log.Print("Y", err) } else { for _, msg := range msgs { genl := (*nlgo.GenlMsghdr)(unsafe.Pointer(&msg.Data[0])) if attr, err := nlgo.Nl80211Policy.Parse(msg.Data[nlgo.GENL_HDRLEN:]); err != nil { log.Print("Z", err) } else { log.Printf("NL80211_CMD_%s attrs=%s", nlgo.NL80211_CMD_itoa[genl.Cmd], attr) } } } } }
// AuditSetEnabled enables or disables audit in kernel. // Provide `enabled` as 1 for enabling and 0 for disabling. func AuditSetEnabled(s *NetlinkConnection, enabled int) error { var ( status auditStatus err error ) status.Enabled = (uint32)(enabled) status.Mask = AUDIT_STATUS_ENABLED buff := new(bytes.Buffer) err = binary.Write(buff, nativeEndian(), status) if err != nil { return errors.Wrap(err, "AuditSetEnabled: binary write from auditStatus failed") } wb := newNetlinkAuditRequest(uint16(AUDIT_SET), syscall.AF_NETLINK, int(unsafe.Sizeof(status))) wb.Data = append(wb.Data[:], buff.Bytes()[:]...) if err := s.Send(wb); err != nil { return errors.Wrap(err, "AuditSetEnabled failed") } // Receive in just one try err = auditGetReply(s, syscall.Getpagesize(), 0, wb.Header.Seq) if err != nil { return errors.Wrap(err, "AuditSetEnabled failed") } return nil }
func (w *Watcher) readAllEvents() { buf := make([]byte, syscall.Getpagesize()) listener, _ := w.listener.(*netlinkListener) for { if w.isDone() { return } nr, _, err := syscall.Recvfrom(listener.sock, buf, 0) if err != nil { w.Error <- err continue } if nr < syscall.NLMSG_HDRLEN { w.Error <- syscall.EINVAL continue } msgs, _ := syscall.ParseNetlinkMessage(buf[:nr]) for _, m := range msgs { if m.Header.Type == syscall.NLMSG_DONE { w.handleEventAll(m.Data) } } } }
func main() { // Turn the eventual fault into a panic, not a program crash, // so that memcopy can recover. debug.SetPanicOnFault(true) size := syscall.Getpagesize() // Map 16 pages of data with a 4-page hole in the middle. data, err := syscall.Mmap(-1, 0, 16*size, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE) if err != nil { log.Fatalf("mmap: %v", err) } // Note: Cannot call syscall.Munmap, because Munmap checks // that you are unmapping a whole region returned by Mmap. // We are trying to unmap just a hole in the middle. if _, _, err := syscall.Syscall(syscall.SYS_MUNMAP, uintptr(unsafe.Pointer(&data[8*size])), uintptr(4*size), 0); err != 0 { log.Fatalf("munmap: %v", err) } other := make([]byte, 16*size) // Check that memcopy returns the actual amount copied // before the fault (8*size - 5, the offset we skip in the argument). n, err := memcopy(data[5:], other) if err == nil { log.Fatal("no error from memcopy across memory hole") } if n != 8*size-5 { log.Fatal("memcopy returned %d, want %d", n, 8*size-5) } }
func TestMmap(t *testing.T) { b, err := syscall.Mmap(-1, 0, syscall.Getpagesize(), syscall.PROT_NONE, syscall.MAP_ANON|syscall.MAP_PRIVATE) if err != nil { t.Fatalf("Mmap: %v", err) } if err := syscall.Munmap(b); err != nil { t.Fatalf("Munmap: %v", err) } }
func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err error) { defer func() { if err != nil { Unmount(target) } }() // Mount options are clipped to page size(4096 bytes). If there are more // layers then these are remounted individually using append. offset := 54 if useDirperm() { offset += len("dirperm1") } b := make([]byte, syscall.Getpagesize()-len(mountLabel)-offset) // room for xino & mountLabel bp := copy(b, fmt.Sprintf("br:%s=rw", rw)) firstMount := true i := 0 for { for ; i < len(ro); i++ { layer := fmt.Sprintf(":%s=ro+wh", ro[i]) if firstMount { if bp+len(layer) > len(b) { break } bp += copy(b[bp:], layer) } else { data := label.FormatMountLabel(fmt.Sprintf("append%s", layer), mountLabel) if err = mount("none", target, "aufs", syscall.MS_REMOUNT, data); err != nil { return } } } if firstMount { opts := "dio,xino=/dev/shm/aufs.xino" if useDirperm() { opts += ",dirperm1" } data := label.FormatMountLabel(fmt.Sprintf("%s,%s", string(b[:bp]), opts), mountLabel) if err = mount("none", target, "aufs", 0, data); err != nil { return } firstMount = false } if i == len(ro) { break } } return }
// TODO: Import gopsutil package and use it instead of // reinventing the wheel. func getSystemInformation() map[string]string { m := make(map[string]string) m["OS"] = runtime.GOOS m["Arch"] = runtime.GOARCH m["Number of CPUs"] = strconv.Itoa(runtime.NumCPU()) m["Mem Page Size (bytes)"] = strconv.Itoa(syscall.Getpagesize()) return m }
func NewRtHub() (*RtHub, error) { self := &RtHub{ sock: NlSocketAlloc(), lock: &sync.Mutex{}, unilock: &sync.Mutex{}, multicast: make(map[uint32][]NetlinkListener), } if err := NlConnect(self.sock, syscall.NETLINK_ROUTE); err != nil { NlSocketFree(self.sock) return nil, err } go func() { for { buf := make([]byte, syscall.Getpagesize()) if n, _, err := syscall.Recvfrom(self.sock.Fd, buf, syscall.MSG_TRUNC); err != nil { if e, ok := err.(syscall.Errno); ok && e.Temporary() { continue } break } else if msgs, err := syscall.ParseNetlinkMessage(buf[:n]); err != nil { break } else { for _, msg := range msgs { multi := func() []NetlinkListener { self.lock.Lock() defer self.lock.Unlock() var ret []NetlinkListener for _, s := range self.multicast { ret = append(ret, s...) } return ret }() if msg.Header.Seq == self.uniseq { if self.unicast != nil { self.unicast.NetlinkListen(msg) } switch msg.Header.Type { case syscall.NLMSG_DONE, syscall.NLMSG_ERROR: self.unilock.Unlock() } } if msg.Header.Seq == 0 { for _, proc := range multi { proc.NetlinkListen(msg) } } } } } log.Print("rt hub loop exit") }() return self, nil }
func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) { rb := make([]byte, syscall.Getpagesize()) nr, _, err := syscall.Recvfrom(s.fd, rb, 0) if err != nil { return nil, err } if nr < syscall.NLMSG_HDRLEN { return nil, ErrShortResponse } rb = rb[:nr] return syscall.ParseNetlinkMessage(rb) }
// Initialize frame buffer device func Init(fbdev, tty string) (*Framebuffer, error) { var fb = new(Framebuffer) var err error fb.tty, err = os.OpenFile(tty, os.O_RDWR, os.ModeDevice) if err != nil { return nil, err } // switch to graphics mode // this prevents kernel modifying the video ram (vt switching/blanking, cursor, gpm mouse cursor) err = ioctl(fb.tty.Fd(), KDSETMODE, unsafe.Pointer(uintptr(KD_GRAPHICS))) if err != nil { fb.tty.Close() return nil, err } fb.dev, err = os.OpenFile(fbdev, os.O_RDWR, os.ModeDevice) if err != nil { fb.tty.Close() return nil, err } err = ioctl(fb.dev.Fd(), FBIOGET_FSCREENINFO, unsafe.Pointer(&fb.finfo)) if err != nil { fb.dev.Close() fb.tty.Close() return nil, err } log.Debug(utils.StructPrint(&fb.finfo)) err = ioctl(fb.dev.Fd(), FBIOGET_VSCREENINFO, unsafe.Pointer(&fb.Vinfo)) if err != nil { fb.dev.Close() fb.tty.Close() return nil, err } log.Debug(utils.StructPrint(&fb.Vinfo)) memSize := int(fb.finfo.Smem_len + uint32(fb.finfo.Smem_start&uint64(syscall.Getpagesize()-1))) fb.Mem, err = syscall.Mmap(int(fb.dev.Fd()), 0, memSize, PROT_READ|PROT_WRITE, MAP_SHARED) if err != nil { fb.dev.Close() fb.tty.Close() return nil, err } fb.MemOffscreen = make([]byte, memSize) return fb, nil }
// Get creates and mounts the required file system for the given id and returns the mount path. func (d *Driver) Get(id string, mountLabel string) (s string, err error) { dir := d.dir(id) if _, err := os.Stat(dir); err != nil { return "", err } diffDir := path.Join(dir, "diff") lowers, err := ioutil.ReadFile(path.Join(dir, lowerFile)) if err != nil { // If no lower, just return diff directory if os.IsNotExist(err) { return diffDir, nil } return "", err } mergedDir := path.Join(dir, "merged") if count := d.ctr.Increment(mergedDir); count > 1 { return mergedDir, nil } defer func() { if err != nil { if c := d.ctr.Decrement(mergedDir); c <= 0 { syscall.Unmount(mergedDir, 0) } } }() workDir := path.Join(dir, "work") opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", string(lowers), path.Join(id, "diff"), path.Join(id, "work")) mountLabel = label.FormatMountLabel(opts, mountLabel) if len(mountLabel) > syscall.Getpagesize() { return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountLabel)) } if err := mountFrom(d.home, "overlay", path.Join(id, "merged"), "overlay", mountLabel); err != nil { return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err) } // chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a // user namespace requires this to move a directory from lower to upper. rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) if err != nil { return "", err } if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil { return "", err } return mergedDir, nil }
// genl_ctrl_probe_by_name is not exposed in the original libnl func GenlCtrlProbeByName(sk *NlSock, name string) (AttrMap, error) { if err := GenlSendSimple(sk, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, CTRL_VERSION, syscall.NLM_F_DUMP); err != nil { return AttrMap{}, err } var ret AttrMap err := func() error { for { buf := make([]byte, syscall.Getpagesize()) if nn, _, err := syscall.Recvfrom(sk.Fd, buf, syscall.MSG_TRUNC); err != nil { return err } else if nn > len(buf) { return NLE_MSG_TRUNC } else { buf = buf[:nn] } if msgs, err := syscall.ParseNetlinkMessage(buf); err != nil { return err } else { for _, msg := range msgs { switch msg.Header.Type { case GENL_ID_CTRL: genl := (*GenlMsghdr)(unsafe.Pointer(&msg.Data[0])) switch genl.Cmd { case CTRL_CMD_NEWFAMILY: if attrs, err := CtrlPolicy.Parse(msg.Data[GENL_HDRLEN:]); err != nil { return err } else if info, ok := attrs.(AttrMap); !ok { // shold not happen } else if value := info.Get(CTRL_ATTR_FAMILY_NAME); value == nil { // should not happen by kernel } else if string(value.(NulString)) == name { ret = info } default: return fmt.Errorf("unexpected command") } case syscall.NLMSG_DONE: return nil case syscall.NLMSG_ERROR: return fmt.Errorf("NlMsgerr=%s", (*syscall.NlMsgerr)(unsafe.Pointer(&msg.Data[0]))) default: return fmt.Errorf("unexpected NlMsghdr=%s", msg.Header) } } } } }() return ret, err }
func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) { if s.fd < 0 { return nil, fmt.Errorf("Receive called on a closed socket") } rb := make([]byte, syscall.Getpagesize()) nr, _, err := syscall.Recvfrom(s.fd, rb, 0) if err != nil { return nil, err } if nr < syscall.NLMSG_HDRLEN { return nil, fmt.Errorf("Got short response from netlink") } rb = rb[:nr] return syscall.ParseNetlinkMessage(rb) }
func main() { flag.Usage = usage flag.Parse() if flag.NArg() != 1 { usage() } f, err := os.OpenFile(flag.Arg(0), os.O_RDWR, 0644) ck(err) defer f.Close() fi, err := f.Stat() ck(err) pagesize := syscall.Getpagesize() pages := fi.Size()/int64(pagesize) - 1 var swap [8192]byte put4(swap[0:], 1) put4(swap[4:], uint32(pages)) seek(f, 1024) uuid := createUUID() copy(swap[4*3:], uuid) if *label != "" { i := 0 for ; i < len(*label) && i < 16; i++ { swap[7*4+i] = (*label)[i] } if i < 16 { swap[7*4+i] = 0 } } write(f, swap[:129*4]) seek(f, int64(pagesize)-10) write(f, []byte("SWAPSPACE2")) syscall.Fsync(int(f.Fd())) f.Close() var str string if *label != "" { str = fmt.Sprintf(", LABEL=%s", *label) } fmt.Printf("Swapspace size: %dk%s, UUID=%s\n", pages*(int64(pagesize)/1024), str, showUUID(uuid)) }
func (s *NetlinkSocket) recv(peer uint32) (*NlMsgParser, error) { buf := MakeAlignedByteSlice(syscall.Getpagesize()) nr, from, err := syscall.Recvfrom(s.fd, buf, 0) if err != nil { return nil, err } switch nlfrom := from.(type) { case *syscall.SockaddrNetlink: if nlfrom.Pid != peer { return nil, fmt.Errorf("wrong netlink peer pid (expected %d, got %d)", peer, nlfrom.Pid) } return &NlMsgParser{data: buf[:nr], pos: 0}, nil default: return nil, fmt.Errorf("Expected netlink sockaddr, got %s", reflect.TypeOf(from)) } }
// This basic rtnetlink example lists up link interfaces. func Example() { sock := NlSocketAlloc() defer NlSocketFree(sock) if err := NlConnect(sock, syscall.NETLINK_ROUTE); err != nil { panic(err) } req := make([]byte, NLMSG_ALIGN(syscall.SizeofIfInfomsg)) if err := NlSendSimple(sock, syscall.RTM_GETLINK, syscall.NLM_F_DUMP, req); err != nil { panic(err) } func() { for { buf := make([]byte, syscall.Getpagesize()) if nn, _, err := syscall.Recvfrom(sock.Fd, buf, syscall.MSG_TRUNC); err != nil { panic(err) } else if nn > len(buf) { panic("out of recv buf") } else { buf = buf[:nn] } if msgs, err := syscall.ParseNetlinkMessage(buf); err != nil { panic(err) } else { for _, msg := range msgs { switch msg.Header.Type { case syscall.RTM_NEWLINK: ifinfo := (*syscall.IfInfomsg)(unsafe.Pointer(&msg.Data[0])) if attrs, err := RouteLinkPolicy.Parse(msg.Data[NLA_ALIGN(syscall.SizeofIfInfomsg):]); err != nil { panic(err) } else { log.Print("ifinfomsg=", ifinfo, " attrs=", attrs) } case syscall.NLMSG_DONE: return default: log.Print("unhandled msg", msg.Header) } } } } }() }
func NewSocket(groups uint32) (file *UeventSocket, e error) { file = nil fd, e := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_DGRAM, syscall.NETLINK_KOBJECT_UEVENT) if e != nil { return } sockaddr := &syscall.SockaddrNetlink{Family: syscall.AF_NETLINK, Pid: 0, Groups: groups} e = syscall.Bind(fd, sockaddr) if e != nil { return } tmp := os.NewFile(uintptr(fd), "NetLink - KOBJECT") file = &UeventSocket{ file: tmp, refs: make(map[string]*KObject, 50), tmpbuff: make([]byte, syscall.Getpagesize()), prenum: make([]chan *KObject, 20), } return }
func checkMemoryUsage(limit int64) { var residentMemory int64 var procStatContents string pageSize := int64(syscall.Getpagesize()) if b, e := ioutil.ReadFile("/proc/self/statm"); e == nil { procStatContents = string(b) } fields := strings.Fields(procStatContents) if len(fields) >= (STATM_FIELD_END - 1) { if stat_value, e := strconv.ParseInt(fields[statm_resident], 10, 64); e == nil { residentMemory = stat_value * pageSize } } if residentMemory > limit { printAgentMemoryStats() panic("Memory usage is too high (" + strconv.FormatInt(residentMemory, 10) + " > " + strconv.FormatInt(limit, 10) + "), Increase memory limit or need to decrease memory usage") } }
func parseVMStat(out string, vms *VirtualMemoryStat) error { var err error lines := strings.Split(out, "\n") pagesize := uint64(syscall.Getpagesize()) for _, line := range lines { fields := strings.Split(line, ":") if len(fields) < 2 { continue } key := strings.TrimSpace(fields[0]) value := strings.Trim(fields[1], " .") switch key { case "Pages free": free, e := strconv.ParseUint(value, 10, 64) if e != nil { err = e } vms.Free = free * pagesize case "Pages inactive": inactive, e := strconv.ParseUint(value, 10, 64) if e != nil { err = e } vms.Inactive = inactive * pagesize case "Pages active": active, e := strconv.ParseUint(value, 10, 64) if e != nil { err = e } vms.Active = active * pagesize case "Pages wired down": wired, e := strconv.ParseUint(value, 10, 64) if e != nil { err = e } vms.Wired = wired * pagesize } } return err }
// AuditSetPID sends a message to kernel for setting of program PID func AuditSetPID(s *NetlinkConnection, pid int) error { var status auditStatus status.Mask = AUDIT_STATUS_PID status.Pid = (uint32)(pid) buff := new(bytes.Buffer) err := binary.Write(buff, nativeEndian(), status) if err != nil { return errors.Wrap(err, "AuditSetPID: binary write from auditStatus failed") } wb := newNetlinkAuditRequest(uint16(AUDIT_SET), syscall.AF_NETLINK, int(unsafe.Sizeof(status))) wb.Data = append(wb.Data[:], buff.Bytes()[:]...) if err := s.Send(wb); err != nil { return errors.Wrap(err, "AuditSetPID failed") } err = auditGetReply(s, syscall.Getpagesize(), 0, wb.Header.Seq) if err != nil { return errors.Wrap(err, "AuditSetPID failed") } return nil }
func TestEqualNearPageBoundary(t *testing.T) { pagesize := syscall.Getpagesize() b := make([]byte, 4*pagesize) i := pagesize for ; uintptr(unsafe.Pointer(&b[i]))%uintptr(pagesize) != 0; i++ { } syscall.Mprotect(b[i-pagesize:i], 0) syscall.Mprotect(b[i+pagesize:i+2*pagesize], 0) defer syscall.Mprotect(b[i-pagesize:i], syscall.PROT_READ|syscall.PROT_WRITE) defer syscall.Mprotect(b[i+pagesize:i+2*pagesize], syscall.PROT_READ|syscall.PROT_WRITE) // both of these should fault //pagesize += int(b[i-1]) //pagesize += int(b[i+pagesize]) for j := 0; j < pagesize; j++ { b[i+j] = 'A' } for j := 0; j <= pagesize; j++ { Equal(b[i:i+j], b[i+pagesize-j:i+pagesize]) Equal(b[i+pagesize-j:i+pagesize], b[i:i+j]) } }
// Sends a message to kernel to turn on audit func AuditSetEnabled(s *NetlinkSocket) error { var status AuditStatus status.Enabled = 1 status.Mask = AUDIT_STATUS_ENABLED buff := new(bytes.Buffer) err := binary.Write(buff, nativeEndian(), status) if err != nil { log.Println("binary.Write failed:", err) return err } wb := newNetlinkAuditRequest(uint16(AUDIT_SET), syscall.AF_NETLINK, int(unsafe.Sizeof(status))) wb.Data = append(wb.Data[:], buff.Bytes()[:]...) if err := s.Send(wb); err != nil { return err } // Receiving IN JUST ONE TRY err = AuditGetReply(s, syscall.Getpagesize(), 0, wb.Header.Seq) if err != nil { return err } return nil }
func (nl *NetlinkSocket) SendMessage(msg *NetlinkMessage, sockflags int, ack bool) error { msg.Header.Len = syscall.NLMSG_HDRLEN + uint32(len(msg.Data)) msg.Header.Seq = nl.nextSeq() if ack { msg.Header.Flags = msg.Header.Flags | syscall.NLM_F_ACK } logf("sent: %+v\n", msg) err := syscall.Sendto(nl.sfd, msg.toWireFormat(), sockflags, &nl.lsa) if err != nil { return err } if ack { msgList, err := nl.RecvMessages(syscall.Getpagesize(), syscall.O_NONBLOCK) if err != nil || len(msgList) > 1 { return errors.New("cannot receive messages") } } return nil }
// VirtualMemory returns VirtualmemoryStat. func VirtualMemory() (*VirtualMemoryStat, error) { count := C.mach_msg_type_number_t(C.HOST_VM_INFO_COUNT) var vmstat C.vm_statistics_data_t status := C.host_statistics(C.host_t(C.mach_host_self()), C.HOST_VM_INFO, C.host_info_t(unsafe.Pointer(&vmstat)), &count) if status != C.KERN_SUCCESS { return nil, fmt.Errorf("host_statistics error=%d", status) } pageSize := uint64(syscall.Getpagesize()) total, err := getHwMemsize() if err != nil { return nil, err } totalCount := C.natural_t(total / pageSize) availableCount := vmstat.inactive_count + vmstat.free_count usedPercent := 100 * float64(totalCount-availableCount) / float64(totalCount) usedCount := totalCount - availableCount return &VirtualMemoryStat{ Total: total, Available: pageSize * uint64(availableCount), Used: pageSize * uint64(usedCount), UsedPercent: usedPercent, Free: pageSize * uint64(vmstat.free_count), Active: pageSize * uint64(vmstat.active_count), Inactive: pageSize * uint64(vmstat.inactive_count), Wired: pageSize * uint64(vmstat.wire_count), }, nil }
func AuditSetBacklogLimit(s *NetlinkSocket, limit int) error { var foo AuditStatus foo.Mask = AUDIT_STATUS_BACKLOG_LIMIT foo.Backlog_limit = (uint32)(limit) buff := new(bytes.Buffer) err := binary.Write(buff, nativeEndian(), foo) if err != nil { log.Println("binary.Write failed:", err) return err } wb := newNetlinkAuditRequest(uint16(AUDIT_SET), syscall.AF_NETLINK, int(unsafe.Sizeof(foo))) wb.Data = append(wb.Data[:], buff.Bytes()[:]...) if err := s.Send(wb); err != nil { return err } err = AuditGetReply(s, syscall.Getpagesize(), 0, wb.Header.Seq) if err != nil { return err } return nil }
// Sends a message to kernel for setting of program pid func AuditSetPid(s *NetlinkSocket, pid uint32 /*,Wait mode WAIT_YES | WAIT_NO */) error { var status AuditStatus status.Mask = AUDIT_STATUS_PID status.Pid = pid buff := new(bytes.Buffer) err := binary.Write(buff, nativeEndian(), status) if err != nil { log.Println("binary.Write failed:", err) return err } wb := newNetlinkAuditRequest(uint16(AUDIT_SET), syscall.AF_NETLINK, int(unsafe.Sizeof(status))) wb.Data = append(wb.Data[:], buff.Bytes()[:]...) if err := s.Send(wb); err != nil { return err } err = AuditGetReply(s, syscall.Getpagesize(), 0, wb.Header.Seq) if err != nil { return err } //Polling in GO Is it needed ? return nil }
func (e Errno) errno() int32 { return int32(e) } func (e Errno) String() string { return syscall.Errno(e).Error() } func (h *Header) RespondError(err Error) { // FUSE uses negative errors! // TODO: File bug report against OSXFUSE: positive error causes kernel panic. out := &outHeader{Error: -err.errno(), Unique: uint64(h.ID)} h.Conn.respond(out, unsafe.Sizeof(*out)) } var maxWrite = syscall.Getpagesize() var bufSize = 4096 + maxWrite // a message represents the bytes of a single FUSE message type message struct { conn *Conn buf []byte // all bytes hdr *inHeader // header off int // offset for reading additional fields } func newMessage(c *Conn) *message { m := &message{conn: c, buf: make([]byte, bufSize)} m.hdr = (*inHeader)(unsafe.Pointer(&m.buf[0])) return m }
// Get creates and mounts the required file system for the given id and returns the mount path. func (d *Driver) Get(id string, mountLabel string) (s string, err error) { dir := d.dir(id) if _, err := os.Stat(dir); err != nil { return "", err } diffDir := path.Join(dir, "diff") lowers, err := ioutil.ReadFile(path.Join(dir, lowerFile)) if err != nil { // If no lower, just return diff directory if os.IsNotExist(err) { return diffDir, nil } return "", err } mergedDir := path.Join(dir, "merged") if count := d.ctr.Increment(mergedDir); count > 1 { return mergedDir, nil } defer func() { if err != nil { if c := d.ctr.Decrement(mergedDir); c <= 0 { syscall.Unmount(mergedDir, 0) } } }() workDir := path.Join(dir, "work") splitLowers := strings.Split(string(lowers), ":") absLowers := make([]string, len(splitLowers)) for i, s := range splitLowers { absLowers[i] = path.Join(d.home, s) } opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), path.Join(dir, "diff"), path.Join(dir, "work")) mountData := label.FormatMountLabel(opts, mountLabel) mount := syscall.Mount mountTarget := mergedDir pageSize := syscall.Getpagesize() // Go can return a larger page size than supported by the system // as of go 1.7. This will be fixed in 1.8 and this block can be // removed when building with 1.8. // See https://github.com/golang/go/commit/1b9499b06989d2831e5b156161d6c07642926ee1 // See https://github.com/docker/docker/issues/27384 if pageSize > 4096 { pageSize = 4096 } // Use relative paths and mountFrom when the mount data has exceeded // the page size. The mount syscall fails if the mount data cannot // fit within a page and relative links make the mount data much // smaller at the expense of requiring a fork exec to chroot. if len(mountData) > pageSize { opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", string(lowers), path.Join(id, "diff"), path.Join(id, "work")) mountData = label.FormatMountLabel(opts, mountLabel) if len(mountData) > pageSize { return "", fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData)) } mount = func(source string, target string, mType string, flags uintptr, label string) error { return mountFrom(d.home, source, target, mType, flags, label) } mountTarget = path.Join(id, "merged") } if err := mount("overlay", mountTarget, "overlay", 0, mountData); err != nil { return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err) } // chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a // user namespace requires this to move a directory from lower to upper. rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) if err != nil { return "", err } if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil { return "", err } return mergedDir, nil }
// Getpagesize returns the underlying system's memory page size. func Getpagesize() int { return syscall.Getpagesize() }
_verOffset = _magicOffset + _verSize _paddingOffset = _verOffset + _paddingSize _paddingByte = byte(0) // ver Ver1 = byte(1) // limits // offset aligned 8 bytes, 4GB * needle_padding_size _maxSize = 4 * 1024 * 1024 * 1024 * needle.PaddingSize _maxOffset = 4294967295 ) var ( _magic = []byte{0xab, 0xcd, 0xef, 0x00} _ver = []byte{Ver1} _padding = bytes.Repeat([]byte{_paddingByte}, _paddingSize) _pagesize = syscall.Getpagesize() ) // An Volume contains one superblock and many needles. type SuperBlock struct { r *os.File w *os.File File string `json:"file"` Offset uint32 `json:"offset"` Size int64 `json:"size"` LastErr error `json:"last_err"` Ver byte `json:"ver"` Options Options `json:"options"` magic []byte `json:"-"` Padding uint32 `json:"padding"` // status