Skip to content

BUG/MINOR: setuid is called before setgid #411

@Benjamin-Paul

Description

@Benjamin-Paul

Hi !

It looks like setuid is called before setgid in main.go :

if err = syscall.Setuid(cfg.HAProxy.UID); err != nil {

if err = syscall.Setgid(cfg.HAProxy.GID); err != nil {

I think that this makes it impossible to set both UID to an unprivileged user and GID, because setuid will be issued first and setgid will then produce the following error if the new user lacks the CAP_SETGID capability (even if the dataplane API was originally started as root) :

set gid: operation not permitted

Steps to reproduce

Simple Dockerfile using the official image haproxytech/haproxy-debian:s6-3.3.10 and creating an unprivileged user (but still running as root) :

FROM docker.io/haproxytech/haproxy-debian:s6-3.3.10

RUN groupadd --gid 1001 unprivileged && \
useradd --uid 1001 --gid unprivileged --shell /bin/false --no-create-home unprivileged

COPY haproxy.cfg dataplaneapi.yml /usr/local/etc/haproxy/

EXPOSE 80 5555

CMD ["/init"]

Basic dataplaneapi.yml file setting both uid and gid to 1001 :

config_version: 2
name: bug-reproduction
dataplaneapi:
  host: 0.0.0.0
  port: 5555
  uid: 1001
  gid: 1001
  scheme:
    - http
  userlist:
    userlist: dataplaneapi
haproxy:
  config_file: /usr/local/etc/haproxy/haproxy.cfg
  haproxy_bin: /usr/local/sbin/haproxy
  reload:
    reload_delay: 5
    service_name: haproxy
    reload_strategy: s6
log_targets:
  - log_to: stdout
    log_level: info
    log_types:
      - access
      - app

Dummy haproxy.cfg :

global
    log /dev/log local0
    log /dev/log local1 notice

    stats socket /var/run/haproxy.sock mode 660 level admin

    daemon
    maxconn 2000

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5s
    timeout client  30s
    timeout server  30s

userlist dataplaneapi
    user admin insecure-password pwd

frontend http_front
    bind *:80
    default_backend web_servers

backend web_servers
    balance roundrobin
    server web1 192.168.1.101:80 check
    server web2 192.168.1.102:80 check

listen stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 10s

Build :

podman build -t haproxy-dataplane-test .

Run :

podman run --name bug-reproduction -d -p 8080:80 -p 5555:5555 haproxy-dataplane-test

And check logs :

podman logs -f bug-reproduction
[...]
set gid: operation not permitted
[...]

Would a contribution to swap the order of setuid and setgid in main.go be welcome or is it something that can be addressed some other way ?

Thanks in advance for your time,

Benjamin

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions