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 }