LINUX.ORG.RU

Нельзя привязаться к порту 443 несмотря на setcap

 ,


0

3

Компилирую такую программу:

package main

import (
	"flag"
	"log"
	"net"
)

var addr = flag.String("http", ":443", "")

func main() {
	_, err := net.Listen("tcp", *addr)
	if err != nil {
		log.Fatal(err)
	}
}


Делаю ей setcap 'cap_net_bind_service=+ep'

Запускаю.

А оно мне: listen tcp :443: bind: permission denied

Что за фигня? ЧЯДНТ?

В логах strace имеется следующее:

bind(4, {sa_family=AF_INET6, sin6_port=htons(443), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EACCES (Permission denied)

Ответ на: комментарий от beastie

Go не поддерживает дроп привилегий.

Вот только что попробовал на другой машине (Debian) - setcap отрабатывает штатно. А на моей Gentoo - фиг вам. Конфигурация ядра как-то влияет?

meskalin
() автор топика

Если заменить tcp на tcp4, то же самое. То есть дело не в IPv6.

meskalin
() автор топика
Ответ на: комментарий от beastie

У меня и есть «Linux with POSIX capabilities». На FreeBSD запускать не собираюсь.

meskalin
() автор топика
Ответ на: комментарий от meskalin

Ты про cap_net_bind_service? Да, костыль, который не работает даже уже сейчас.

Я не знаю, что ты из syscall собрался ломать в следующем релизе.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)

Ядро 4.8.3, опции CONFIG_SECURITY_FILE_CAPABILITIES нет (я так понимаю, она по умолчанию и неотключаема).

meskalin
() автор топика
Ответ на: комментарий от meskalin

а проверить setcap на каком-нибудь бинаре, врoде ping?

anonymous
()

Подписался, интересно. У меня заработало с eip, но потом почему-то стало работать и с ep, после того как я поигрался с runtime.LockOSThread() и вернул обратно. Черт знает, что за херня. Вполне вероятно, что ломается из-за шедулера — я почти уверен, что main выполняется не в том же потоке, который был автоматически создан при запуске процесса, а capability set — per-thread attribute.

Deleted
()
Ответ на: комментарий от beastie

В тегах нет POSIX, прекрати оффтопить и покинь тред плиз.

Deleted
()

Я смутно припоминаю, что capability должна быть и у пользователя.

tailgunner ★★★★★
()

Удивительно, но Go тут ни при чём, похоже. Код на C пишет то же самое:

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>

int
make_socket (uint16_t port)
{
  int sock;
  struct sockaddr_in name;

  /* Create the socket. */
  sock = socket (PF_INET, SOCK_STREAM, 0);
  if (sock < 0)
    {
      perror ("socket");
      exit (EXIT_FAILURE);
    }

  /* Give the socket a name. */
  name.sin_family = AF_INET;
  name.sin_port = htons (port);
  name.sin_addr.s_addr = htonl (INADDR_ANY);
  if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0)
    {
      perror ("bind");
      exit (EXIT_FAILURE);
    }

  return sock;
}

int main() {
	make_socket(443);
	return 0;
}
meskalin
() автор топика

Нашёл в гугле:

File capabilities are not assigned when the program being executed is located on a filesystem mounted with the «nosuid» option.

А у меня $HOME как раз ecryptfs (rw,nosuid,nodev,relatime,ecryptfs_fnek_sig=...,ecryptfs_sig=...,ecryptfs_cipher=aes,ecryptfs_key_bytes=16,ecryptfs_unlink_sigs).

На / всё работает. Тему можно закрывать.

meskalin
() автор топика
Ответ на: комментарий от meskalin

Тему можно закрывать.

Закрыл.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.