gitee.com/mysnapcore/mysnapd@v0.1.0/polkit/pid_start_time.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  //go:build linux
     3  // +build linux
     4  
     5  /*
     6   * Copyright (C) 2017 Canonical Ltd
     7   *
     8   * This program is free software: you can redistribute it and/or modify
     9   * it under the terms of the GNU General Public License version 3 as
    10   * published by the Free Software Foundation.
    11   *
    12   * This program is distributed in the hope that it will be useful,
    13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15   * GNU General Public License for more details.
    16   *
    17   * You should have received a copy of the GNU General Public License
    18   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    19   *
    20   */
    21  
    22  package polkit
    23  
    24  import (
    25  	"fmt"
    26  	"io/ioutil"
    27  	"strconv"
    28  	"strings"
    29  )
    30  
    31  // getStartTimeForPid determines the start time for a given process ID
    32  func getStartTimeForPid(pid int32) (uint64, error) {
    33  	filename := fmt.Sprintf("/proc/%d/stat", pid)
    34  	return getStartTimeForProcStatFile(filename)
    35  }
    36  
    37  // getStartTimeForProcStatFile determines the start time from a process stat file
    38  //
    39  // The implementation is intended to be compatible with polkit:
    40  //    https://cgit.freedesktop.org/polkit/tree/src/polkit/polkitunixprocess.c
    41  func getStartTimeForProcStatFile(filename string) (uint64, error) {
    42  	data, err := ioutil.ReadFile(filename)
    43  	if err != nil {
    44  		return 0, err
    45  	}
    46  	contents := string(data)
    47  
    48  	// start time is the token at index 19 after the '(process
    49  	// name)' entry - since only this field can contain the ')'
    50  	// character, search backwards for this to avoid malicious
    51  	// processes trying to fool us
    52  	//
    53  	// See proc(5) man page for a description of the
    54  	// /proc/[pid]/stat file format and the meaning of the
    55  	// starttime field.
    56  	idx := strings.IndexByte(contents, ')')
    57  	if idx < 0 {
    58  		return 0, fmt.Errorf("cannot parse %s", filename)
    59  	}
    60  	idx += 2 // skip ") "
    61  	if idx > len(contents) {
    62  		return 0, fmt.Errorf("cannot parse %s", filename)
    63  	}
    64  	tokens := strings.Split(contents[idx:], " ")
    65  	if len(tokens) < 20 {
    66  		return 0, fmt.Errorf("cannot parse %s", filename)
    67  	}
    68  	return strconv.ParseUint(tokens[19], 10, 64)
    69  }