Manually start a second AstraLinux session as another user on a virtual display with low integrity level

I need to run a session as user2 from an already running session of user1 on a virtual display and I need to keep the integrity level low. Here is my implementation of the Go code to start the session:

type LaunchService struct {
displayNumberID string
customEnv       []string
displayNumber   int
processes       map[string]int
ConnStatus      models.Status
log             *zerolog.Logger
sListener       *SocketListener
execCommand     func(name string, arg ...string) *exec.Cmd
}

func NewLaunchService(zlog *zerolog.Logger, sList *SocketListener) *LaunchService {
env := os.Environ()
dispNumber := 99
dispID := fmt.Sprintf(":%d", dispNumber)
env = append(env, fmt.Sprintf(`DISPLAY=%s`, dispID))
lService := &LaunchService{
    customEnv:       env,
    log:             zlog,
    displayNumber:   dispNumber,
    displayNumberID: dispID,
    sListener:       sList,
    ConnStatus:      -1,
    processes:       make(map[string]int),
    execCommand:     exec.Command,
}
return lService
}

func (ls *LaunchService) StartDesktopSession(authData models.AuthData) error {
if err := ls.TerminateAllProcesses(); err != nil {
    return err
}
group, _ := errgroup.WithContext(context.Background())
group.Go(func() error {
    if err := ls.initEnvironment(authData.Username); err != nil {
        return err
    }
    return nil
})
ls.log.Debug().Msg("Starting a graphical session")
group.Go(func() error {
    if err := ls.startXVFB(authData); err != nil {
        ls.log.Error().Err(err).Msg("Error when start xvfb-run")
        return err
    }
    return nil
})
time.Sleep(time.Second)
group.Go(func() error {
    if err := ls.startDesktop(authData.Username, authData.Desktop); err != nil {
        return err
    }
    return nil
})
time.Sleep(time.Second)
group.Go(func() error {
    if err := ls.startGlint(authData.Username); err != nil {
        return err
    }
    return nil
})
time.Sleep(time.Second)
group.Go(func() error {
    if err := ls.startPulseaudio(authData.Username); err != nil {
        return err
    }
    return nil
})
time.Sleep(time.Second)

if err := group.Wait(); err != nil {
    return err
}
return nil
}

func (ls *LaunchService) initEnvironment(usrname string) error {
ls.log.Debug().Msg("start audio")
cmd := ls.execCommand("sudo", "usermod", "-aG", "audio", usrname)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
    ls.log.Error().Err(err).Msg("Error when authorizing the use of the sound card")
    return fmt.Errorf(errText.AuthSoundCardErr, err)
}
cmd = ls.execCommand("sudo", "mkhomedir_helper", usrname)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
    ls.log.Error().Err(err).Msg("error when creating a home directory for a user " + usrname)
    return fmt.Errorf(errText.MkHomeDirErr, usrname, err)
}
ls.log.Debug().Msg("starting audio finished")
return nil
}

func (ls *LaunchService) startXVFB(auth models.AuthData) error {
if err := ls.deleteTempFiles(); err != nil {
    return err
}
ls.log.Debug().Msg("start XVFB")
cmd := ls.execCommand("sudo", "-u", auth.Username, "Xvfb", ls.displayNumberID,
    "-screen", "0", fmt.Sprintf("%dx%dx%d", auth.Width, auth.Height, auth.Depth))
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
    ls.log.Error().Err(err).Msg("Error when authorizing the use of the sound card")
    return fmt.Errorf(errText.XVFBStartErr, err)
}
time.Sleep(time.Second)
if err := ls.writeProcess("Xvfb"); err != nil {
    return err
}
ls.log.Debug().Msg("starting XVFB finished")
return nil
}

func (ls *LaunchService) startDesktop(usrname string, desktop string) error {
ls.log.Debug().Msg("start desktop")
cmd := ls.execCommand("sudo", "-u", usrname, "fly-wm", "--noparse")
ls.log.Debug().Any("cmd args", cmd.Args).Msg("Check startDesktop comm args")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = ls.customEnv
if err := cmd.Start(); err != nil {
    ls.log.Error().Err(err).Msg("Error when starting desktop")
    return fmt.Errorf(errText.XFCEStartErr, err)
}
time.Sleep(time.Second)
if err := ls.writeProcess("fly-wm"); err != nil {
    return err
}
ls.log.Debug().Str("desktop environment", desktop).Msg("starting desktop finished")
return nil
}

func (ls *LaunchService) startPulseaudio(usrname string) error {
ls.log.Debug().Msg("start pulseaudio")
cmd := ls.execCommand("sudo", "-u", usrname, "pulseaudio")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
    ls.log.Error().Err(err).Msg("Error when starting pulseaudio")
    return fmt.Errorf(errText.PulseAudioStartErr, err)
}
ls.log.Debug().Int("pulseaudio pid", cmd.Process.Pid).Msg("Process id pulseaudio")
ls.processes["pulseaudio"] = cmd.Process.Pid
ls.log.Debug().Msg("starting pulseaudio finished")
return nil
}

func (ls *LaunchService) deleteTempFiles() error {
xUnix := fmt.Sprintf("/tmp/.X11-unix/X%d", ls.displayNumber)
xLock := fmt.Sprintf("/tmp/.X%d-lock", ls.displayNumber)
xUnixExist, err := isFileExist(xUnix)
if err != nil {
    return err
}
xLockExist, err := isFileExist(xLock)
if err != nil {
    return err
}
if xUnixExist {
    if err = os.Remove(xUnix); err != nil {
        ls.log.Error().Err(err).Msg("Error when deleting " + xUnix)
        return fmt.Errorf(errText.TemtDeleteErr, xUnix, err)
    }
}
if xLockExist {
    if err = os.Remove(xLock); err != nil {
        ls.log.Error().Err(err).Msg("Error when deleting " + xLock)
        return fmt.Errorf(errText.TemtDeleteErr, xLock, err)
    }
}
return nil
}

Before running Authenticate the user with the following code:

func pamAuth(usrName, passwd string) error {
if err := clearFaillog(usrName); err != nil {
    return err
}
transaction, err := pam.StartFunc("login", usrName, func(style pam.Style, msg string) (string, error) {
    if style == pam.PromptEchoOff {
        return passwd, nil
    }
    return "", fmt.Errorf(errTexts.PAMPromitErr, msg)
})

if err != nil {
    return err
}

if err = transaction.Authenticate(0); err != nil {
    return fmt.Errorf(errTexts.PAMAuthErr, err)
}
return nil
}

When you run this code, the session starts, but the integrity level check (pdp-id command) shows a high integrity level. Most likely, since the code is run under sudo as user1 (the code is run as a systemd service) integrity is inherited.

Tried limiting user2's max integrity to low, but the integrity level is still high when the session starts. I tried to start fly-dm and log in manually, but in this case just a black screen.

I also noticed the following warnings in the logs, but I couldn't deal with them:

** (process:24121): WARNING **: 17:15:57.307: Unable to register authentication agent: 
GDBus.Error:org.freedesktop.PolicyKit1.Error.Failed: User of caller and user of subject differs.
"Cannot register authentication agent: 
GDBus.Error:org.freedesktop.PolicyKit1.Error.Failed: User of caller and user of subject differs."
Authentication agent result: false
Couldn't register listener!
QDBusArgument: read from a write-only object
QDBusArgument: read from a write-only object
QDBusArgument: read from a write-only object
fly-wm [14:15:57] err: IceProcessMessagesIOError, state=0: client 
'1c2737472000172234895700000241030005' '(null)'
fly-wm [14:15:57] err: ICE Connection closed due to 
IceProcessMessagesIOError!

Upvotes: 1

Views: 65

Answers (0)

Related Questions