Merge lp:~cjwatson/ubuntu/trusty/rsyslog/repair-groups into lp:ubuntu/trusty/rsyslog

Proposed by Colin Watson
Status: Merged
Merged at revision: 57
Proposed branch: lp:~cjwatson/ubuntu/trusty/rsyslog/repair-groups
Merge into: lp:ubuntu/trusty/rsyslog
Diff against target: 1533 lines (+1468/-0)
7 files modified
.pc/10-initgroups.patch/runtime/rsconf.c (+1386/-0)
.pc/applied-patches (+1/-0)
debian/changelog (+12/-0)
debian/patches/10-initgroups.patch (+44/-0)
debian/patches/series (+1/-0)
debian/rsyslog.postinst (+6/-0)
runtime/rsconf.c (+18/-0)
To merge this branch: bzr merge lp:~cjwatson/ubuntu/trusty/rsyslog/repair-groups
Reviewer Review Type Date Requested Status
Martin Pitt Approve
Review via email: mp+197705@code.launchpad.net

Description of the change

This fixes log file creation in trusty. IRC conversation for the record:

<pitti> xnox_, slangasek: I adjusted bug 1257633; apparently rsyslog is now completely unable to create any of its logs?
<ubottu> bug 1257633 in rsyslog (Ubuntu Trusty) "/var/log/syslog and others don't exist on fresh installation of Trusty." [Critical,Confirmed] https://launchpad.net/bugs/1257633
<cjwatson> pitti: I'm investigating that at the moment, bug 1256695
<ubottu> bug 1256695 in rsyslog (Ubuntu) "Trusty desktop Installation logs are not copied to /var/log/installer/" [Undecided,Confirmed] https://launchpad.net/bugs/1256695
<cjwatson> pitti: it seems to be to do with a rearrangement of how privilege-dropping works
<pitti> cjwatson: ah, thank you
<cjwatson> +- bugfix: do not open files with full privileges, if privs will be dropped
<cjwatson> + This make the privilege drop code more bulletproof, but breaks Ubuntu's
<cjwatson> + work-around for log files created by external programs with the wrong
<cjwatson> + user and/or group. Note that it was long said that this "functionality"
<cjwatson> + would break once we go for serious privilege drop code, so hopefully
<cjwatson> + nobody still depends on it (and, if so, they lost...).
<cjwatson> e.g.
<cjwatson> so, uh, oh dear
<pitti> cjwatson: ah, that's because /var/log is root:root 755?
<cjwatson> Yeah, it might be as simple as changing that
<cjwatson> I see that rsyslog-controlled files there were already syslog:adm
<pitti> rsyslog runs as syslog:syslog, so we could just make it root:syslog 775?
<cjwatson> that's certainly sufficient to make it work
<cjwatson> I can't immediately think of a reason not to do that
<cjwatson> what do other distros do?
<cjwatson> it's not clear to me that Fedora drops privileges, looking only at its rsyslog packaging
<pitti> cjwatson: do they even use rsyslog still? it's not all journald now?
<pitti> I understand you can still install it, but it's not by default
<cjwatson> Nor Gentoo
<cjwatson> pitti: could be
<cjwatson> pitti: however, there's a further difficulty
<cjwatson> pitti: if I just change the /var/log perms, then it appears to work, but /var/log/syslog is created syslog:syslog not syslog:adm, so the ability for users in group adm to read logs has been broken
<cjwatson> (and mode 640)
<cjwatson> pitti: this is related to bug 484336
<ubottu> bug 484336 in rsyslog (Ubuntu) "/etc/rsyslog.conf permissions incorrect/missing for creation of dynamic files" [Undecided,Confirmed] https://launchpad.net/bugs/484336
<pitti> cjwatson: ah, so we'd need to put user "syslog" into "adm", or perhaps even make that its primary group?
<pitti> (that's ugly to do on upgrades, though)
<cjwatson> or run rsyslogd as group adm
<cjwatson> I don't know which is worse
<cjwatson> we have to do one of those if rsyslogd is no longer willing to use raised privileges to open files, though ...
<cjwatson> it wouldn't need to be syslog's primary group
<cjwatson> syslog is a dynamic user owned by the rsyslog package, so it's not necessarily horrible to change its supplementary groups
<cjwatson> hmm, that doesn't fix the ownership though
<pitti> right, with a non-primary groupd it'd need a source patch
<cjwatson> oh, because rsyslogd doesn't setgroups when it drops privileges?
<cjwatson> or rather it does but only to deliberately drop supplementary groups
<pitti> cjwatson: no, I meant if it creates a new file, it would need to explicitly set their group to "adm", unless that's its primary group?
<cjwatson> it's already configured with FileGroup to do that
<pitti> ah, of course; sorry
<cjwatson> but the problem is that it can only do the chown() if it did the appropriate setgroups at privdrop
<cjwatson> http://kb.monitorware.com/feature-request-privdroptogroup-setgroups-initgroups-t11491.html
<pitti> $PrivDropToGroup syslog
<pitti> so that's what's not keeping the aux groups
<cjwatson> right. now the questions would be (a) would changing that to adm expose rsyslog to any malice by users in group adm? (b) might there be systems right now that are relying on rsyslog being able to open files in group syslog?
<pitti> I don't see an immediate case for (a) as "adm" is pretty much only a "get read privs" group, but (b) certainly might happen
<cjwatson> the link above has an example of situations where you want rsyslogd to be able to set different log files to be owned by different groups
<pitti> cjwatson: TBH it seems safer to me to change the code to not drop the aux groups
<cjwatson> dropping the aux groups is required to drop the root group, but it could call initgroups afterwards
<cjwatson> pitti: Considering something like http://paste.ubuntu.com/6519272/
<pitti> cjwatson: I'm a bit rusty on the order of the various set* calls; does initgroups() come before or after setgid()?
<pitti> cjwatson: AFAIR, you have to setgid(), then initgroups(), then setuid(), right?
<cjwatson> pitti: rsyslog calls doDropPrivGid then doDropPrivUid
<pitti> the patch looks like initgroups() would come after set[ug]id?
<pitti> ah, so these two hunks are not from one functino
<cjwatson> pitti: doDropPrivGid already calls setgroups before setgid to discard the previously-held supplementary groups
<cjwatson> pitti: they are
<pitti> cjwatson: ack; LGTM then, thank you!
<cjwatson> pitti: the important bit is that you have to drop the old groups before you lose the ability to do so
<pitti> cjwatson: but this is still missing a chgrp syslog /var/log, isn't it?
<cjwatson> pitti: I think initgroups is fine after setuid
<cjwatson> pitti: oh yes good point
<pitti> cjwatson: after setuid> that's surprising; that sounds like increasing privileges after you dropped them and shouldn't be able to get them any more?
<cjwatson> I think you can gain your own supplementary groups ... but wait, something just occurred to me
<pitti> cjwatson: (and chmod 775)
<cjwatson> /var/log must not be owned by group adm
<cjwatson> because if we do that then users in group adm will be able to add files to it
<cjwatson> which is not expected
<pitti> no, adm group members must nto be able to write there
<pitti> that's why I thought root:syslog would be better
<cjwatson> oh, right, yeah, too many pieces
<pitti> so that rsyslog can write into it, but no real users
 * pitti adds to this TODO list to create an autopkgtest for rsyslog to cover new logs, log rotation, etc.
<cjwatson> http://paste.ubuntu.com/6519302/ then
<pitti> cjwatson: chmod g+w /var/log ?
<cjwatson> added
<cjwatson> pitti: hm, you were right earlier, setgroups (called by initgroups) requires the CAP_SETGID capability
<cjwatson> so I'll move that before the setuid
<pitti> ok, that's relieving (would be weird otherwise)
<cjwatson> pitti: OK, so after some fixups this basically works, but there's an amusing complication
<cjwatson> pitti: On upgrade, we restart rsyslog in postinst rather than stop in prerm / start in postinst, for generally obvious reasons
<cjwatson> pitti: But this means that when it restarts it tries to log one final message to say it's shutting down (and others might racily be logged, of course)
<cjwatson> pitti: And on a system without /var/log/syslog, that last message now gets successfully written (since we just adjusted permissions) but /var/log/syslog ends up as syslog:syslog (since we hadn't yet completed the restart with supplementary groups)
<cjwatson> pitti: So, I don't know; I suppose we could choose to not care because it's only been a problem for five days or so and it would go away at the next logrotate
<cjwatson> pitti: wdyt?
<pitti> cjwatson: re (sorry, lunch)
<pitti> cjwatson: TBH I'd go with the "don't care" approach, as it didn't affect any stables
<pitti> cjwatson: and in trusty, logs are already broken anyway
<pitti> cjwatson: i. e. the fully "correct" solution would be to create the file in preinst with the correct permissions on upgrade?
<cjwatson> pitti: well, except that the race case could involve log messages going to any log file
<cjwatson> I'm cool with "don't care" if you are :-)
<pitti> I am
<pitti> the main conclusion I draw from this is "this needs an autopkgtest" :)

To post a comment you must log in.
Revision history for this message
Martin Pitt (pitti) wrote :

Looks good to me, thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory '.pc/10-initgroups.patch'
=== added directory '.pc/10-initgroups.patch/runtime'
=== added file '.pc/10-initgroups.patch/runtime/rsconf.c'
--- .pc/10-initgroups.patch/runtime/rsconf.c 1970-01-01 00:00:00 +0000
+++ .pc/10-initgroups.patch/runtime/rsconf.c 2013-12-04 13:07:52 +0000
@@ -0,0 +1,1386 @@
1/* rsconf.c - the rsyslog configuration system.
2 *
3 * Module begun 2011-04-19 by Rainer Gerhards
4 *
5 * Copyright 2011-2012 Adiscon GmbH.
6 *
7 * This file is part of the rsyslog runtime library.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 * -or-
15 * see COPYING.ASL20 in the source distribution
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23#include "config.h"
24#include <stdio.h>
25#include <stdlib.h>
26#include <assert.h>
27#include <string.h>
28#include <errno.h>
29#include <unistd.h>
30#include <grp.h>
31#include <stdarg.h>
32#include <sys/resource.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35
36#include "rsyslog.h"
37#include "obj.h"
38#include "srUtils.h"
39#include "ruleset.h"
40#include "modules.h"
41#include "conf.h"
42#include "queue.h"
43#include "rsconf.h"
44#include "cfsysline.h"
45#include "errmsg.h"
46#include "action.h"
47#include "glbl.h"
48#include "unicode-helper.h"
49#include "omshell.h"
50#include "omusrmsg.h"
51#include "omfwd.h"
52#include "omfile.h"
53#include "ompipe.h"
54#include "omdiscard.h"
55#include "pmrfc5424.h"
56#include "pmrfc3164.h"
57#include "smfile.h"
58#include "smtradfile.h"
59#include "smfwd.h"
60#include "smtradfwd.h"
61#include "parser.h"
62#include "outchannel.h"
63#include "threads.h"
64#include "datetime.h"
65#include "parserif.h"
66#include "modules.h"
67#include "dirty.h"
68#include "template.h"
69
70extern char* yytext;
71/* static data */
72DEFobjStaticHelpers
73DEFobjCurrIf(ruleset)
74DEFobjCurrIf(module)
75DEFobjCurrIf(conf)
76DEFobjCurrIf(errmsg)
77DEFobjCurrIf(glbl)
78DEFobjCurrIf(parser)
79DEFobjCurrIf(datetime)
80
81/* exported static data */
82rsconf_t *runConf = NULL;/* the currently running config */
83rsconf_t *loadConf = NULL;/* the config currently being loaded (no concurrent config load supported!) */
84
85/* hardcoded standard templates (used for defaults) */
86static uchar template_DebugFormat[] = "\"Debug line with all properties:\nFROMHOST: '%FROMHOST%', fromhost-ip: '%fromhost-ip%', HOSTNAME: '%HOSTNAME%', PRI: %PRI%,\nsyslogtag '%syslogtag%', programname: '%programname%', APP-NAME: '%APP-NAME%', PROCID: '%PROCID%', MSGID: '%MSGID%',\nTIMESTAMP: '%TIMESTAMP%', STRUCTURED-DATA: '%STRUCTURED-DATA%',\nmsg: '%msg%'\nescaped msg: '%msg:::drop-cc%'\ninputname: %inputname% rawmsg: '%rawmsg%'\n\n\"";
87static uchar template_SyslogProtocol23Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n\"";
88static uchar template_TraditionalFileFormat[] = "=RSYSLOG_TraditionalFileFormat";
89static uchar template_FileFormat[] = "=RSYSLOG_FileFormat";
90static uchar template_ForwardFormat[] = "=RSYSLOG_ForwardFormat";
91static uchar template_TraditionalForwardFormat[] = "=RSYSLOG_TraditionalForwardFormat";
92static uchar template_WallFmt[] = "\"\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n %syslogtag%%msg%\n\r\"";
93static uchar template_StdUsrMsgFmt[] = "\" %syslogtag%%msg%\n\r\"";
94static uchar template_StdDBFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')\",SQL";
95static uchar template_StdPgSQLFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-pgsql%', '%timegenerated:::date-pgsql%', %iut%, '%syslogtag%')\",STDSQL";
96static uchar template_spoofadr[] = "\"%fromhost-ip%\"";
97static uchar template_SysklogdFileFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg%\n\"";
98static uchar template_StdJSONFmt[] = "\"{\\\"message\\\":\\\"%msg:::json%\\\",\\\"fromhost\\\":\\\"%HOSTNAME:::json%\\\",\\\"facility\\\":\\\"%syslogfacility-text%\\\",\\\"priority\\\":\\\"%syslogpriority-text%\\\",\\\"timereported\\\":\\\"%timereported:::date-rfc3339%\\\",\\\"timegenerated\\\":\\\"%timegenerated:::date-rfc3339%\\\"}\"";
99/* end templates */
100
101/* tables for interfacing with the v6 config system (as far as we need to) */
102static struct cnfparamdescr inppdescr[] = {
103 { "type", eCmdHdlrString, CNFPARAM_REQUIRED }
104};
105static struct cnfparamblk inppblk =
106 { CNFPARAMBLK_VERSION,
107 sizeof(inppdescr)/sizeof(struct cnfparamdescr),
108 inppdescr
109 };
110
111/* forward-definitions */
112void cnfDoCfsysline(char *ln);
113
114/* Standard-Constructor
115 */
116BEGINobjConstruct(rsconf) /* be sure to specify the object type also in END macro! */
117 pThis->globals.bDebugPrintTemplateList = 1;
118 pThis->globals.bDebugPrintModuleList = 0;
119 pThis->globals.bDebugPrintCfSysLineHandlerList = 0;
120 pThis->globals.bLogStatusMsgs = DFLT_bLogStatusMsgs;
121 pThis->globals.bErrMsgToStderr = 1;
122 pThis->globals.umask = -1;
123 pThis->templates.root = NULL;
124 pThis->templates.last = NULL;
125 pThis->templates.lastStatic = NULL;
126 pThis->actions.nbrActions = 0;
127 CHKiRet(llInit(&pThis->rulesets.llRulesets, rulesetDestructForLinkedList,
128 rulesetKeyDestruct, strcasecmp));
129 /* queue params */
130 pThis->globals.mainQ.iMainMsgQueueSize = 10000;
131 pThis->globals.mainQ.iMainMsgQHighWtrMark = 8000;
132 pThis->globals.mainQ.iMainMsgQLowWtrMark = 2000;
133 pThis->globals.mainQ.iMainMsgQDiscardMark = 9800;
134 pThis->globals.mainQ.iMainMsgQDiscardSeverity = 8;
135 pThis->globals.mainQ.iMainMsgQueueNumWorkers = 1;
136 pThis->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
137 pThis->globals.mainQ.pszMainMsgQFName = NULL;
138 pThis->globals.mainQ.iMainMsgQueMaxFileSize = 1024*1024;
139 pThis->globals.mainQ.iMainMsgQPersistUpdCnt = 0;
140 pThis->globals.mainQ.bMainMsgQSyncQeueFiles = 0;
141 pThis->globals.mainQ.iMainMsgQtoQShutdown = 1500;
142 pThis->globals.mainQ.iMainMsgQtoActShutdown = 1000;
143 pThis->globals.mainQ.iMainMsgQtoEnq = 2000;
144 pThis->globals.mainQ.iMainMsgQtoWrkShutdown = 60000;
145 pThis->globals.mainQ.iMainMsgQWrkMinMsgs = 100;
146 pThis->globals.mainQ.iMainMsgQDeqSlowdown = 0;
147 pThis->globals.mainQ.iMainMsgQueMaxDiskSpace = 0;
148 pThis->globals.mainQ.iMainMsgQueDeqBatchSize = 32;
149 pThis->globals.mainQ.bMainMsgQSaveOnShutdown = 1;
150 pThis->globals.mainQ.iMainMsgQueueDeqtWinFromHr = 0;
151 pThis->globals.mainQ.iMainMsgQueueDeqtWinToHr = 25;
152 /* end queue params */
153finalize_it:
154ENDobjConstruct(rsconf)
155
156
157/* ConstructionFinalizer
158 */
159rsRetVal rsconfConstructFinalize(rsconf_t __attribute__((unused)) *pThis)
160{
161 DEFiRet;
162 ISOBJ_TYPE_assert(pThis, rsconf);
163 RETiRet;
164}
165
166
167/* call freeCnf() module entry points AND free the module entries themselfes.
168 */
169static inline void
170freeCnf(rsconf_t *pThis)
171{
172 cfgmodules_etry_t *etry, *del;
173 etry = pThis->modules.root;
174 while(etry != NULL) {
175 if(etry->pMod->beginCnfLoad != NULL) {
176 dbgprintf("calling freeCnf(%p) for module '%s'\n",
177 etry->modCnf, (char*) module.GetName(etry->pMod));
178 etry->pMod->freeCnf(etry->modCnf);
179 }
180 del = etry;
181 etry = etry->next;
182 free(del);
183 }
184}
185
186
187/* destructor for the rsconf object */
188BEGINobjDestruct(rsconf) /* be sure to specify the object type also in END and CODESTART macros! */
189CODESTARTobjDestruct(rsconf)
190 freeCnf(pThis);
191 tplDeleteAll(pThis);
192 free(pThis->globals.mainQ.pszMainMsgQFName);
193 free(pThis->globals.pszConfDAGFile);
194 llDestroy(&(pThis->rulesets.llRulesets));
195ENDobjDestruct(rsconf)
196
197
198/* DebugPrint support for the rsconf object */
199BEGINobjDebugPrint(rsconf) /* be sure to specify the object type also in END and CODESTART macros! */
200 cfgmodules_etry_t *modNode;
201
202 dbgprintf("configuration object %p\n", pThis);
203 dbgprintf("Global Settings:\n");
204 dbgprintf(" bDebugPrintTemplateList.............: %d\n",
205 pThis->globals.bDebugPrintTemplateList);
206 dbgprintf(" bDebugPrintModuleList : %d\n",
207 pThis->globals.bDebugPrintModuleList);
208 dbgprintf(" bDebugPrintCfSysLineHandlerList.....: %d\n",
209 pThis->globals.bDebugPrintCfSysLineHandlerList);
210 dbgprintf(" bLogStatusMsgs : %d\n",
211 pThis->globals.bLogStatusMsgs);
212 dbgprintf(" bErrMsgToStderr.....................: %d\n",
213 pThis->globals.bErrMsgToStderr);
214 dbgprintf(" drop Msgs with malicious PTR Record : %d\n",
215 glbl.GetDropMalPTRMsgs());
216 ruleset.DebugPrintAll(pThis);
217 dbgprintf("\n");
218 if(pThis->globals.bDebugPrintTemplateList)
219 tplPrintList(pThis);
220 if(pThis->globals.bDebugPrintModuleList)
221 module.PrintList();
222 if(pThis->globals.bDebugPrintCfSysLineHandlerList)
223 dbgPrintCfSysLineHandlers();
224 // TODO: The following code needs to be "streamlined", so far just moved over...
225 dbgprintf("Main queue size %d messages.\n", pThis->globals.mainQ.iMainMsgQueueSize);
226 dbgprintf("Main queue worker threads: %d, wThread shutdown: %d, Perists every %d updates.\n",
227 pThis->globals.mainQ.iMainMsgQueueNumWorkers,
228 pThis->globals.mainQ.iMainMsgQtoWrkShutdown, pThis->globals.mainQ.iMainMsgQPersistUpdCnt);
229 dbgprintf("Main queue timeouts: shutdown: %d, action completion shutdown: %d, enq: %d\n",
230 pThis->globals.mainQ.iMainMsgQtoQShutdown,
231 pThis->globals.mainQ.iMainMsgQtoActShutdown, pThis->globals.mainQ.iMainMsgQtoEnq);
232 dbgprintf("Main queue watermarks: high: %d, low: %d, discard: %d, discard-severity: %d\n",
233 pThis->globals.mainQ.iMainMsgQHighWtrMark, pThis->globals.mainQ.iMainMsgQLowWtrMark,
234 pThis->globals.mainQ.iMainMsgQDiscardMark, pThis->globals.mainQ.iMainMsgQDiscardSeverity);
235 dbgprintf("Main queue save on shutdown %d, max disk space allowed %lld\n",
236 pThis->globals.mainQ.bMainMsgQSaveOnShutdown, pThis->globals.mainQ.iMainMsgQueMaxDiskSpace);
237 /* TODO: add
238 iActionRetryCount = 0;
239 iActionRetryInterval = 30000;
240 static int iMainMsgQtoWrkMinMsgs = 100;
241 static int iMainMsgQbSaveOnShutdown = 1;
242 iMainMsgQueMaxDiskSpace = 0;
243 setQPROP(qqueueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", 100);
244 setQPROP(qqueueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", 1);
245 */
246 dbgprintf("Work Directory: '%s'.\n", glbl.GetWorkDir());
247 ochPrintList();
248 dbgprintf("Modules used in this configuration:\n");
249 for(modNode = pThis->modules.root ; modNode != NULL ; modNode = modNode->next) {
250 dbgprintf(" %s\n", module.GetName(modNode->pMod));
251 }
252CODESTARTobjDebugPrint(rsconf)
253ENDobjDebugPrint(rsconf)
254
255
256/* This function returns the current date in different
257 * variants. It is used to construct the $NOW series of
258 * system properties. The returned buffer must be freed
259 * by the caller when no longer needed. If the function
260 * can not allocate memory, it returns a NULL pointer.
261 * TODO: this was taken from msg.c and we should consolidate it with the code
262 * there. This is especially important when we increase the number of system
263 * variables (what we definitely want to do).
264 */
265typedef enum ENOWType { NOW_NOW, NOW_YEAR, NOW_MONTH, NOW_DAY, NOW_HOUR, NOW_MINUTE } eNOWType;
266static rsRetVal
267getNOW(eNOWType eNow, es_str_t **estr)
268{
269 DEFiRet;
270 uchar szBuf[16];
271 struct syslogTime t;
272 es_size_t len;
273
274 datetime.getCurrTime(&t, NULL);
275 switch(eNow) {
276 case NOW_NOW:
277 len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar),
278 "%4.4d-%2.2d-%2.2d", t.year, t.month, t.day);
279 break;
280 case NOW_YEAR:
281 len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%4.4d", t.year);
282 break;
283 case NOW_MONTH:
284 len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.month);
285 break;
286 case NOW_DAY:
287 len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.day);
288 break;
289 case NOW_HOUR:
290 len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.hour);
291 break;
292 case NOW_MINUTE:
293 len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "%2.2d", t.minute);
294 break;
295 default:
296 len = snprintf((char*) szBuf, sizeof(szBuf)/sizeof(uchar), "*invld eNow*");
297 break;
298 }
299
300 /* now create a string object out of it and hand that over to the var */
301 *estr = es_newStrFromCStr((char*)szBuf, len);
302
303 RETiRet;
304}
305
306
307
308static inline es_str_t *
309getSysVar(char *name)
310{
311 es_str_t *estr = NULL;
312 rsRetVal iRet = RS_RET_OK;
313
314 if(!strcmp(name, "now")) {
315 CHKiRet(getNOW(NOW_NOW, &estr));
316 } else if(!strcmp(name, "year")) {
317 CHKiRet(getNOW(NOW_YEAR, &estr));
318 } else if(!strcmp(name, "month")) {
319 CHKiRet(getNOW(NOW_MONTH, &estr));
320 } else if(!strcmp(name, "day")) {
321 CHKiRet(getNOW(NOW_DAY, &estr));
322 } else if(!strcmp(name, "hour")) {
323 CHKiRet(getNOW(NOW_HOUR, &estr));
324 } else if(!strcmp(name, "minute")) {
325 CHKiRet(getNOW(NOW_MINUTE, &estr));
326 } else if(!strcmp(name, "myhostname")) {
327 char *hn = (char*)glbl.GetLocalHostName();
328 estr = es_newStrFromCStr(hn, strlen(hn));
329 } else {
330 ABORT_FINALIZE(RS_RET_SYSVAR_NOT_FOUND);
331 }
332finalize_it:
333 if(iRet != RS_RET_OK) {
334 dbgprintf("getSysVar error iRet %d\n", iRet);
335 if(estr == NULL)
336 estr = es_newStrFromCStr("*ERROR*", sizeof("*ERROR*") - 1);
337 }
338 return estr;
339}
340
341
342/* Process input() objects */
343rsRetVal
344inputProcessCnf(struct cnfobj *o)
345{
346 struct cnfparamvals *pvals;
347 modInfo_t *pMod;
348 uchar *cnfModName = NULL;
349 int typeIdx;
350 DEFiRet;
351
352 pvals = nvlstGetParams(o->nvlst, &inppblk, NULL);
353 if(pvals == NULL) {
354 ABORT_FINALIZE(RS_RET_CONFIG_ERROR);
355 }
356 DBGPRINTF("input param blk after inputProcessCnf:\n");
357 cnfparamsPrint(&inppblk, pvals);
358 typeIdx = cnfparamGetIdx(&inppblk, "type");
359 cnfModName = (uchar*)es_str2cstr(pvals[typeIdx].val.d.estr, NULL);
360 if((pMod = module.FindWithCnfName(loadConf, cnfModName, eMOD_IN)) == NULL) {
361 errmsg.LogError(0, RS_RET_MOD_UNKNOWN, "input module name '%s' is unknown", cnfModName);
362 ABORT_FINALIZE(RS_RET_MOD_UNKNOWN);
363 }
364 if(pMod->mod.im.newInpInst == NULL) {
365 errmsg.LogError(0, RS_RET_MOD_NO_INPUT_STMT,
366 "input module '%s' does not support input() statement", cnfModName);
367 ABORT_FINALIZE(RS_RET_MOD_NO_INPUT_STMT);
368 }
369 CHKiRet(pMod->mod.im.newInpInst(o->nvlst));
370finalize_it:
371 free(cnfModName);
372 cnfparamvalsDestruct(pvals, &inppblk);
373 RETiRet;
374}
375
376/*------------------------------ interface to flex/bison parser ------------------------------*/
377extern int yylineno;
378
379void
380parser_errmsg(char *fmt, ...)
381{
382 va_list ap;
383 char errBuf[1024];
384
385 va_start(ap, fmt);
386 if(vsnprintf(errBuf, sizeof(errBuf), fmt, ap) == sizeof(errBuf))
387 errBuf[sizeof(errBuf)-1] = '\0';
388 errmsg.LogError(0, RS_RET_CONF_PARSE_ERROR,
389 "error during parsing file %s, on or before line %d: %s",
390 cnfcurrfn, yylineno, errBuf);
391 va_end(ap);
392}
393
394int
395yyerror(char *s)
396{
397 parser_errmsg("%s on token '%s'", s, yytext);
398 return 0;
399}
400void cnfDoObj(struct cnfobj *o)
401{
402 int bChkUnuse = 1;
403
404 dbgprintf("cnf:global:obj: ");
405 cnfobjPrint(o);
406 switch(o->objType) {
407 case CNFOBJ_GLOBAL:
408 glblProcessCnf(o);
409 break;
410 case CNFOBJ_MODULE:
411 modulesProcessCnf(o);
412 break;
413 case CNFOBJ_INPUT:
414 inputProcessCnf(o);
415 break;
416 case CNFOBJ_TPL:
417 if(tplProcessCnf(o) != RS_RET_OK)
418 parser_errmsg("error processing template object");
419 break;
420 case CNFOBJ_RULESET:
421 rulesetProcessCnf(o);
422 break;
423 case CNFOBJ_PROPERTY:
424 case CNFOBJ_CONSTANT:
425 /* these types are processed at a later stage */
426 bChkUnuse = 0;
427 break;
428 default:
429 dbgprintf("cnfDoObj program error: unexpected object type %u\n",
430 o->objType);
431 break;
432 }
433 if(bChkUnuse)
434 nvlstChkUnused(o->nvlst);
435 cnfobjDestruct(o);
436}
437
438void cnfDoScript(struct cnfstmt *script)
439{
440 dbgprintf("cnf:global:script\n");
441 ruleset.AddScript(ruleset.GetCurrent(loadConf), script);
442}
443
444void cnfDoCfsysline(char *ln)
445{
446 DBGPRINTF("cnf:global:cfsysline: %s\n", ln);
447 /* the legacy system needs the "$" stripped */
448 conf.cfsysline((uchar*) ln+1);
449 free(ln);
450}
451
452void cnfDoBSDTag(char *ln)
453{
454 DBGPRINTF("cnf:global:BSD tag: %s\n", ln);
455 errmsg.LogError(0, RS_RET_BSD_BLOCKS_UNSUPPORTED,
456 "BSD-style blocks are no longer supported in rsyslog, "
457 "see http://www.rsyslog.com/g/BSD for details and a "
458 "solution (Block '%s')", ln);
459 free(ln);
460}
461
462void cnfDoBSDHost(char *ln)
463{
464 DBGPRINTF("cnf:global:BSD host: %s\n", ln);
465 errmsg.LogError(0, RS_RET_BSD_BLOCKS_UNSUPPORTED,
466 "BSD-style blocks are no longer supported in rsyslog, "
467 "see http://www.rsyslog.com/g/BSD for details and a "
468 "solution (Block '%s')", ln);
469 free(ln);
470}
471
472es_str_t*
473cnfGetVar(char *name, void *usrptr)
474{
475 es_str_t *estr;
476 if(name[0] == '$') {
477 if(name[1] == '$')
478 estr = getSysVar(name+2);
479 else if(name[1] == '!')
480 estr = msgGetCEEVarNew((msg_t*) usrptr, name+2);
481 else
482 estr = msgGetMsgVarNew((msg_t*) usrptr, (uchar*)name+1);
483 } else { /* if this happens, we have a program logic error */
484 estr = es_newStrFromCStr("err: var must start with $",
485 strlen("err: var must start with $"));
486 }
487 if(Debug) {
488 char *s;
489 s = es_str2cstr(estr, NULL);
490 dbgprintf("rainerscript: var '%s': '%s'\n", name, s);
491 free(s);
492 }
493 return estr;
494}
495/*------------------------------ end interface to flex/bison parser ------------------------------*/
496
497
498
499/* drop to specified group
500 * if something goes wrong, the function never returns
501 * Note that such an abort can cause damage to on-disk structures, so we should
502 * re-design the "interface" in the long term. -- rgerhards, 2008-11-26
503 */
504static void doDropPrivGid(int iGid)
505{
506 int res;
507 uchar szBuf[1024];
508
509 res = setgroups(0, NULL); /* remove all supplementary group IDs */
510 if(res) {
511 perror("could not remove supplemental group IDs");
512 exit(1);
513 }
514 DBGPRINTF("setgroups(0, NULL): %d\n", res);
515 res = setgid(iGid);
516 if(res) {
517 /* if we can not set the userid, this is fatal, so let's unconditionally abort */
518 perror("could not set requested group id");
519 exit(1);
520 }
521 DBGPRINTF("setgid(%d): %d\n", iGid, res);
522 snprintf((char*)szBuf, sizeof(szBuf)/sizeof(uchar), "rsyslogd's groupid changed to %d", iGid);
523 logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, szBuf, 0);
524}
525
526
527/* drop to specified user
528 * if something goes wrong, the function never returns
529 * Note that such an abort can cause damage to on-disk structures, so we should
530 * re-design the "interface" in the long term. -- rgerhards, 2008-11-19
531 */
532static void doDropPrivUid(int iUid)
533{
534 int res;
535 uchar szBuf[1024];
536
537 res = setuid(iUid);
538 if(res) {
539 /* if we can not set the userid, this is fatal, so let's unconditionally abort */
540 perror("could not set requested userid");
541 exit(1);
542 }
543 DBGPRINTF("setuid(%d): %d\n", iUid, res);
544 snprintf((char*)szBuf, sizeof(szBuf)/sizeof(uchar), "rsyslogd's userid changed to %d", iUid);
545 logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, szBuf, 0);
546}
547
548
549
550/* drop privileges. This will drop to the configured privileges, if
551 * set by the user. After this method has been executed, the previous
552 * privileges can no be re-gained.
553 */
554static inline rsRetVal
555dropPrivileges(rsconf_t *cnf)
556{
557 DEFiRet;
558
559 /* If instructed to do so, we now drop privileges. Note that this is not 100% secure,
560 * because outputs are already running at this time. However, we can implement
561 * dropping of privileges rather quickly and it will work in many cases. While it is not
562 * the ultimate solution, the current one is still much better than not being able to
563 * drop privileges at all. Doing it correctly, requires a change in architecture, which
564 * we should do over time. TODO -- rgerhards, 2008-11-19
565 */
566 if(cnf->globals.gidDropPriv != 0) {
567 doDropPrivGid(ourConf->globals.gidDropPriv);
568 DBGPRINTF("group privileges have been dropped to gid %u\n", (unsigned)
569 ourConf->globals.gidDropPriv);
570 }
571
572 if(cnf->globals.uidDropPriv != 0) {
573 doDropPrivUid(ourConf->globals.uidDropPriv);
574 DBGPRINTF("user privileges have been dropped to uid %u\n", (unsigned)
575 ourConf->globals.uidDropPriv);
576 }
577
578 RETiRet;
579}
580
581
582/* tell the rsysog core (including ourselfs) that the config load is done and
583 * we need to prepare to move over to activate mode.
584 */
585static inline void
586tellCoreConfigLoadDone(void)
587{
588 glblDoneLoadCnf();
589}
590
591
592/* Tell input modules that the config parsing stage is over. */
593static rsRetVal
594tellModulesConfigLoadDone(void)
595{
596 cfgmodules_etry_t *node;
597
598 BEGINfunc
599 DBGPRINTF("telling modules that config load for %p is done\n", loadConf);
600 node = module.GetNxtCnfType(loadConf, NULL, eMOD_ANY);
601 while(node != NULL) {
602 if(node->pMod->beginCnfLoad != NULL)
603 node->pMod->endCnfLoad(node->modCnf);
604 node = module.GetNxtCnfType(runConf, node, eMOD_IN);
605 }
606
607 ENDfunc
608 return RS_RET_OK; /* intentional: we do not care about module errors */
609}
610
611
612/* Tell input modules to verify config object */
613static rsRetVal
614tellModulesCheckConfig(void)
615{
616 cfgmodules_etry_t *node;
617 rsRetVal localRet;
618
619 BEGINfunc
620 DBGPRINTF("telling modules to check config %p\n", loadConf);
621 node = module.GetNxtCnfType(loadConf, NULL, eMOD_ANY);
622 while(node != NULL) {
623 if(node->pMod->beginCnfLoad != NULL) {
624 localRet = node->pMod->checkCnf(node->modCnf);
625 DBGPRINTF("module %s tells us config can %sbe activated\n",
626 node->pMod->pszName, (localRet == RS_RET_OK) ? "" : "NOT ");
627 if(localRet == RS_RET_OK) {
628 node->canActivate = 1;
629 } else {
630 node->canActivate = 0;
631 }
632 }
633 node = module.GetNxtCnfType(runConf, node, eMOD_IN);
634 }
635
636 ENDfunc
637 return RS_RET_OK; /* intentional: we do not care about module errors */
638}
639
640
641/* Tell modules to activate current running config (pre privilege drop) */
642static rsRetVal
643tellModulesActivateConfigPrePrivDrop(void)
644{
645 cfgmodules_etry_t *node;
646 rsRetVal localRet;
647
648 BEGINfunc
649 DBGPRINTF("telling modules to activate config (before dropping privs) %p\n", runConf);
650 node = module.GetNxtCnfType(runConf, NULL, eMOD_ANY);
651 while(node != NULL) {
652 if( node->pMod->beginCnfLoad != NULL
653 && node->pMod->activateCnfPrePrivDrop != NULL
654 && node->canActivate) {
655 DBGPRINTF("pre priv drop activating config %p for module %s\n",
656 runConf, node->pMod->pszName);
657 localRet = node->pMod->activateCnfPrePrivDrop(node->modCnf);
658 if(localRet != RS_RET_OK) {
659 errmsg.LogError(0, localRet, "activation of module %s failed",
660 node->pMod->pszName);
661 node->canActivate = 0; /* in a sense, could not activate... */
662 }
663 }
664 node = module.GetNxtCnfType(runConf, node, eMOD_IN);
665 }
666
667 ENDfunc
668 return RS_RET_OK; /* intentional: we do not care about module errors */
669}
670
671
672/* Tell modules to activate current running config */
673static rsRetVal
674tellModulesActivateConfig(void)
675{
676 cfgmodules_etry_t *node;
677 rsRetVal localRet;
678
679 BEGINfunc
680 DBGPRINTF("telling modules to activate config %p\n", runConf);
681 node = module.GetNxtCnfType(runConf, NULL, eMOD_ANY);
682 while(node != NULL) {
683 if(node->pMod->beginCnfLoad != NULL && node->canActivate) {
684 DBGPRINTF("activating config %p for module %s\n",
685 runConf, node->pMod->pszName);
686 localRet = node->pMod->activateCnf(node->modCnf);
687 if(localRet != RS_RET_OK) {
688 errmsg.LogError(0, localRet, "activation of module %s failed",
689 node->pMod->pszName);
690 node->canActivate = 0; /* in a sense, could not activate... */
691 }
692 }
693 node = module.GetNxtCnfType(runConf, node, eMOD_IN);
694 }
695
696 ENDfunc
697 return RS_RET_OK; /* intentional: we do not care about module errors */
698}
699
700
701/* Actually run the input modules. This happens after privileges are dropped,
702 * if that is requested.
703 */
704static rsRetVal
705runInputModules(void)
706{
707 cfgmodules_etry_t *node;
708 int bNeedsCancel;
709
710 BEGINfunc
711 node = module.GetNxtCnfType(runConf, NULL, eMOD_IN);
712 while(node != NULL) {
713 if(node->canRun) {
714 bNeedsCancel = (node->pMod->isCompatibleWithFeature(sFEATURENonCancelInputTermination) == RS_RET_OK) ?
715 0 : 1;
716 DBGPRINTF("running module %s with config %p, term mode: %s\n", node->pMod->pszName, node,
717 bNeedsCancel ? "cancel" : "cooperative/SIGTTIN");
718 thrdCreate(node->pMod->mod.im.runInput, node->pMod->mod.im.afterRun, bNeedsCancel,
719 (node->pMod->cnfName == NULL) ? node->pMod->pszName : node->pMod->cnfName);
720 }
721 node = module.GetNxtCnfType(runConf, node, eMOD_IN);
722 }
723
724 ENDfunc
725 return RS_RET_OK; /* intentional: we do not care about module errors */
726}
727
728
729/* Make the modules check if they are ready to start.
730 */
731static rsRetVal
732startInputModules(void)
733{
734 DEFiRet;
735 cfgmodules_etry_t *node;
736
737 node = module.GetNxtCnfType(runConf, NULL, eMOD_IN);
738 while(node != NULL) {
739 if(node->canActivate) {
740 iRet = node->pMod->mod.im.willRun();
741 node->canRun = (iRet == RS_RET_OK);
742 if(!node->canRun) {
743 DBGPRINTF("module %s will not run, iRet %d\n", node->pMod->pszName, iRet);
744 }
745 } else {
746 node->canRun = 0;
747 }
748 node = module.GetNxtCnfType(runConf, node, eMOD_IN);
749 }
750
751 ENDfunc
752 return RS_RET_OK; /* intentional: we do not care about module errors */
753}
754
755
756/* activate the main queue */
757static inline rsRetVal
758activateMainQueue()
759{
760 DEFiRet;
761 /* create message queue */
762 CHKiRet_Hdlr(createMainQueue(&pMsgQueue, UCHAR_CONSTANT("main Q"), NULL)) {
763 /* no queue is fatal, we need to give up in that case... */
764 fprintf(stderr, "fatal error %d: could not create message queue - rsyslogd can not run!\n", iRet);
765 FINALIZE;
766 }
767
768 bHaveMainQueue = (ourConf->globals.mainQ.MainMsgQueType == QUEUETYPE_DIRECT) ? 0 : 1;
769 DBGPRINTF("Main processing queue is initialized and running\n");
770finalize_it:
771 RETiRet;
772}
773
774
775/* set the processes umask (upon configuration request) */
776static inline rsRetVal
777setUmask(int iUmask)
778{
779 if(iUmask != -1) {
780 umask(iUmask);
781 DBGPRINTF("umask set to 0%3.3o.\n", iUmask);
782 }
783
784 return RS_RET_OK;
785}
786
787
788/* Activate an already-loaded configuration. The configuration will become
789 * the new running conf (if successful). Note that in theory this method may
790 * be called when there already is a running conf. In practice, the current
791 * version of rsyslog does not support this. Future versions probably will.
792 * Begun 2011-04-20, rgerhards
793 */
794rsRetVal
795activate(rsconf_t *cnf)
796{
797 DEFiRet;
798
799 /* at this point, we "switch" over to the running conf */
800 runConf = cnf;
801# if 0 /* currently the DAG is not supported -- code missing! */
802 /* TODO: re-enable this functionality some time later! */
803 /* check if we need to generate a config DAG and, if so, do that */
804 if(ourConf->globals.pszConfDAGFile != NULL)
805 generateConfigDAG(ourConf->globals.pszConfDAGFile);
806# endif
807 setUmask(cnf->globals.umask);
808
809 /* the output part and the queue is now ready to run. So it is a good time
810 * to initialize the inputs. Please note that the net code above should be
811 * shuffled to down here once we have everything in input modules.
812 * rgerhards, 2007-12-14
813 * NOTE: as of 2009-06-29, the input modules are initialized, but not yet run.
814 * Keep in mind. though, that the outputs already run if the queue was
815 * persisted to disk. -- rgerhards
816 */
817 tellModulesActivateConfigPrePrivDrop();
818
819 CHKiRet(dropPrivileges(cnf));
820
821 tellModulesActivateConfig();
822 startInputModules();
823 CHKiRet(activateActions());
824 CHKiRet(activateMainQueue());
825 /* finally let the inputs run... */
826 runInputModules();
827
828 dbgprintf("configuration %p activated\n", cnf);
829
830finalize_it:
831 RETiRet;
832}
833
834
835/* -------------------- some legacy config handlers --------------------
836 * TODO: move to conf.c?
837 */
838
839/* legacy config system: set the action resume interval */
840static rsRetVal setActionResumeInterval(void __attribute__((unused)) *pVal, int iNewVal)
841{
842 return actionSetGlobalResumeInterval(iNewVal);
843}
844
845
846/* Switch the default ruleset (that, what servcies bind to if nothing specific
847 * is specified).
848 * rgerhards, 2009-06-12
849 */
850static rsRetVal
851setDefaultRuleset(void __attribute__((unused)) *pVal, uchar *pszName)
852{
853 DEFiRet;
854
855 CHKiRet(ruleset.SetDefaultRuleset(ourConf, pszName));
856
857finalize_it:
858 free(pszName); /* no longer needed */
859 RETiRet;
860}
861
862
863/* Switch to either an already existing rule set or start a new one. The
864 * named rule set becomes the new "current" rule set (what means that new
865 * actions are added to it).
866 * rgerhards, 2009-06-12
867 */
868static rsRetVal
869setCurrRuleset(void __attribute__((unused)) *pVal, uchar *pszName)
870{
871 ruleset_t *pRuleset;
872 rsRetVal localRet;
873 DEFiRet;
874
875 localRet = ruleset.SetCurrRuleset(ourConf, pszName);
876
877 if(localRet == RS_RET_NOT_FOUND) {
878 DBGPRINTF("begin new current rule set '%s'\n", pszName);
879 CHKiRet(ruleset.Construct(&pRuleset));
880 CHKiRet(ruleset.SetName(pRuleset, pszName));
881 CHKiRet(ruleset.ConstructFinalize(ourConf, pRuleset));
882 rulesetSetCurrRulesetPtr(pRuleset);
883 } else {
884 ABORT_FINALIZE(localRet);
885 }
886
887finalize_it:
888 free(pszName); /* no longer needed */
889 RETiRet;
890}
891
892
893/* set the main message queue mode
894 * rgerhards, 2008-01-03
895 */
896static rsRetVal setMainMsgQueType(void __attribute__((unused)) *pVal, uchar *pszType)
897{
898 DEFiRet;
899
900 if (!strcasecmp((char *) pszType, "fixedarray")) {
901 loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
902 DBGPRINTF("main message queue type set to FIXED_ARRAY\n");
903 } else if (!strcasecmp((char *) pszType, "linkedlist")) {
904 loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_LINKEDLIST;
905 DBGPRINTF("main message queue type set to LINKEDLIST\n");
906 } else if (!strcasecmp((char *) pszType, "disk")) {
907 loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_DISK;
908 DBGPRINTF("main message queue type set to DISK\n");
909 } else if (!strcasecmp((char *) pszType, "direct")) {
910 loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_DIRECT;
911 DBGPRINTF("main message queue type set to DIRECT (no queueing at all)\n");
912 } else {
913 errmsg.LogError(0, RS_RET_INVALID_PARAMS, "unknown mainmessagequeuetype parameter: %s", (char *) pszType);
914 iRet = RS_RET_INVALID_PARAMS;
915 }
916 free(pszType); /* no longer needed */
917
918 RETiRet;
919}
920
921
922/* -------------------- end legacy config handlers -------------------- */
923
924
925/* set the processes max number ob files (upon configuration request)
926 * 2009-04-14 rgerhards
927 */
928static rsRetVal setMaxFiles(void __attribute__((unused)) *pVal, int iFiles)
929{
930// TODO this must use a local var, then carry out action during activate!
931 struct rlimit maxFiles;
932 char errStr[1024];
933 DEFiRet;
934
935 maxFiles.rlim_cur = iFiles;
936 maxFiles.rlim_max = iFiles;
937
938 if(setrlimit(RLIMIT_NOFILE, &maxFiles) < 0) {
939 /* NOTE: under valgrind, we seem to be unable to extend the size! */
940 rs_strerror_r(errno, errStr, sizeof(errStr));
941 errmsg.LogError(0, RS_RET_ERR_RLIM_NOFILE, "could not set process file limit to %d: %s [kernel max %ld]",
942 iFiles, errStr, (long) maxFiles.rlim_max);
943 ABORT_FINALIZE(RS_RET_ERR_RLIM_NOFILE);
944 }
945#ifdef USE_UNLIMITED_SELECT
946 glbl.SetFdSetSize(howmany(iFiles, __NFDBITS) * sizeof (fd_mask));
947#endif
948 DBGPRINTF("Max number of files set to %d [kernel max %ld].\n", iFiles, (long) maxFiles.rlim_max);
949
950finalize_it:
951 RETiRet;
952}
953
954
955/* legacy config system: reset config variables to default values. */
956static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
957{
958 loadConf->globals.bLogStatusMsgs = DFLT_bLogStatusMsgs;
959 loadConf->globals.bDebugPrintTemplateList = 1;
960 loadConf->globals.bDebugPrintCfSysLineHandlerList = 1;
961 loadConf->globals.bDebugPrintModuleList = 1;
962 loadConf->globals.bAbortOnUncleanConfig = 0;
963 loadConf->globals.bReduceRepeatMsgs = 0;
964 free(loadConf->globals.mainQ.pszMainMsgQFName);
965 loadConf->globals.mainQ.pszMainMsgQFName = NULL;
966 loadConf->globals.mainQ.iMainMsgQueueSize = 10000;
967 loadConf->globals.mainQ.iMainMsgQHighWtrMark = 8000;
968 loadConf->globals.mainQ.iMainMsgQLowWtrMark = 2000;
969 loadConf->globals.mainQ.iMainMsgQDiscardMark = 9800;
970 loadConf->globals.mainQ.iMainMsgQDiscardSeverity = 8;
971 loadConf->globals.mainQ.iMainMsgQueMaxFileSize = 1024 * 1024;
972 loadConf->globals.mainQ.iMainMsgQueueNumWorkers = 1;
973 loadConf->globals.mainQ.iMainMsgQPersistUpdCnt = 0;
974 loadConf->globals.mainQ.bMainMsgQSyncQeueFiles = 0;
975 loadConf->globals.mainQ.iMainMsgQtoQShutdown = 1500;
976 loadConf->globals.mainQ.iMainMsgQtoActShutdown = 1000;
977 loadConf->globals.mainQ.iMainMsgQtoEnq = 2000;
978 loadConf->globals.mainQ.iMainMsgQtoWrkShutdown = 60000;
979 loadConf->globals.mainQ.iMainMsgQWrkMinMsgs = 100;
980 loadConf->globals.mainQ.iMainMsgQDeqSlowdown = 0;
981 loadConf->globals.mainQ.bMainMsgQSaveOnShutdown = 1;
982 loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
983 loadConf->globals.mainQ.iMainMsgQueMaxDiskSpace = 0;
984 loadConf->globals.mainQ.iMainMsgQueDeqBatchSize = 32;
985
986 return RS_RET_OK;
987}
988
989
990/* legacy config system: set the action resume interval */
991static rsRetVal
992setModDir(void __attribute__((unused)) *pVal, uchar* pszNewVal)
993{
994 DEFiRet;
995 iRet = module.SetModDir(pszNewVal);
996 free(pszNewVal);
997 RETiRet;
998}
999
1000
1001/* "load" a build in module and register it for the current load config */
1002static rsRetVal
1003regBuildInModule(rsRetVal (*modInit)(), uchar *name, void *pModHdlr)
1004{
1005 cfgmodules_etry_t *pNew;
1006 cfgmodules_etry_t *pLast;
1007 modInfo_t *pMod;
1008 DEFiRet;
1009 CHKiRet(module.doModInit(modInit, name, pModHdlr, &pMod));
1010 readyModForCnf(pMod, &pNew, &pLast);
1011 addModToCnfList(pNew, pLast);
1012finalize_it:
1013 RETiRet;
1014}
1015
1016
1017/* load build-in modules
1018 * very first version begun on 2007-07-23 by rgerhards
1019 */
1020static rsRetVal
1021loadBuildInModules()
1022{
1023 DEFiRet;
1024
1025 CHKiRet(regBuildInModule(modInitFile, UCHAR_CONSTANT("builtin:omfile"), NULL));
1026 CHKiRet(regBuildInModule(modInitPipe, UCHAR_CONSTANT("builtin:ompipe"), NULL));
1027 CHKiRet(regBuildInModule(modInitShell, UCHAR_CONSTANT("builtin-shell"), NULL));
1028 CHKiRet(regBuildInModule(modInitDiscard, UCHAR_CONSTANT("builtin:omdiscard"), NULL));
1029# ifdef SYSLOG_INET
1030 CHKiRet(regBuildInModule(modInitFwd, UCHAR_CONSTANT("builtin:omfwd"), NULL));
1031# endif
1032
1033 /* dirty, but this must be for the time being: the usrmsg module must always be
1034 * loaded as last module. This is because it processes any type of action selector.
1035 * If we load it before other modules, these others will never have a chance of
1036 * working with the config file. We may change that implementation so that a user name
1037 * must start with an alnum, that would definitely help (but would it break backwards
1038 * compatibility?). * rgerhards, 2007-07-23
1039 * User names now must begin with:
1040 * [a-zA-Z0-9_.]
1041 */
1042 CHKiRet(regBuildInModule(modInitUsrMsg, (uchar*) "builtin:omusrmsg", NULL));
1043
1044 /* load build-in parser modules */
1045 CHKiRet(regBuildInModule(modInitpmrfc5424, UCHAR_CONSTANT("builtin:pmrfc5424"), NULL));
1046 CHKiRet(regBuildInModule(modInitpmrfc3164, UCHAR_CONSTANT("builtin:pmrfc3164"), NULL));
1047
1048 /* and set default parser modules. Order is *very* important, legacy
1049 * (3164) parser needs to go last! */
1050 CHKiRet(parser.AddDfltParser(UCHAR_CONSTANT("rsyslog.rfc5424")));
1051 CHKiRet(parser.AddDfltParser(UCHAR_CONSTANT("rsyslog.rfc3164")));
1052
1053 /* load build-in strgen modules */
1054 CHKiRet(regBuildInModule(modInitsmfile, UCHAR_CONSTANT("builtin:smfile"), NULL));
1055 CHKiRet(regBuildInModule(modInitsmtradfile, UCHAR_CONSTANT("builtin:smtradfile"), NULL));
1056 CHKiRet(regBuildInModule(modInitsmfwd, UCHAR_CONSTANT("builtin:smfwd"), NULL));
1057 CHKiRet(regBuildInModule(modInitsmtradfwd, UCHAR_CONSTANT("builtin:smtradfwd"), NULL));
1058
1059finalize_it:
1060 if(iRet != RS_RET_OK) {
1061 /* we need to do fprintf, as we do not yet have an error reporting system
1062 * in place.
1063 */
1064 fprintf(stderr, "fatal error: could not activate built-in modules. Error code %d.\n",
1065 iRet);
1066 }
1067 RETiRet;
1068}
1069
1070
1071/* intialize the legacy config system */
1072static inline rsRetVal
1073initLegacyConf(void)
1074{
1075 DEFiRet;
1076 uchar *pTmp;
1077 ruleset_t *pRuleset;
1078
1079 DBGPRINTF("doing legacy config system init\n");
1080 /* construct the default ruleset */
1081 ruleset.Construct(&pRuleset);
1082 ruleset.SetName(pRuleset, UCHAR_CONSTANT("RSYSLOG_DefaultRuleset"));
1083 ruleset.ConstructFinalize(loadConf, pRuleset);
1084 rulesetSetCurrRulesetPtr(pRuleset);
1085
1086 /* now register config handlers */
1087 CHKiRet(regCfSysLineHdlr((uchar *)"sleep", 0, eCmdHdlrGoneAway,
1088 NULL, NULL, NULL));
1089 CHKiRet(regCfSysLineHdlr((uchar *)"logrsyslogstatusmessages", 0, eCmdHdlrBinary,
1090 NULL, &loadConf->globals.bLogStatusMsgs, NULL));
1091 CHKiRet(regCfSysLineHdlr((uchar *)"errormessagestostderr", 0, eCmdHdlrBinary,
1092 NULL, &loadConf->globals.bErrMsgToStderr, NULL));
1093 CHKiRet(regCfSysLineHdlr((uchar *)"abortonuncleanconfig", 0, eCmdHdlrBinary,
1094 NULL, &loadConf->globals.bAbortOnUncleanConfig, NULL));
1095 CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgreduction", 0, eCmdHdlrBinary,
1096 NULL, &loadConf->globals.bReduceRepeatMsgs, NULL));
1097 CHKiRet(regCfSysLineHdlr((uchar *)"debugprinttemplatelist", 0, eCmdHdlrBinary,
1098 NULL, &(loadConf->globals.bDebugPrintTemplateList), NULL));
1099 CHKiRet(regCfSysLineHdlr((uchar *)"debugprintmodulelist", 0, eCmdHdlrBinary,
1100 NULL, &(loadConf->globals.bDebugPrintModuleList), NULL));
1101 CHKiRet(regCfSysLineHdlr((uchar *)"debugprintcfsyslinehandlerlist", 0, eCmdHdlrBinary,
1102 NULL, &(loadConf->globals.bDebugPrintCfSysLineHandlerList), NULL));
1103 CHKiRet(regCfSysLineHdlr((uchar *)"privdroptouser", 0, eCmdHdlrUID,
1104 NULL, &loadConf->globals.uidDropPriv, NULL));
1105 CHKiRet(regCfSysLineHdlr((uchar *)"privdroptouserid", 0, eCmdHdlrInt,
1106 NULL, &loadConf->globals.uidDropPriv, NULL));
1107 CHKiRet(regCfSysLineHdlr((uchar *)"privdroptogroup", 0, eCmdHdlrGID,
1108 NULL, &loadConf->globals.gidDropPriv, NULL));
1109 CHKiRet(regCfSysLineHdlr((uchar *)"privdroptogroupid", 0, eCmdHdlrGID,
1110 NULL, &loadConf->globals.gidDropPriv, NULL));
1111 CHKiRet(regCfSysLineHdlr((uchar *)"generateconfiggraph", 0, eCmdHdlrGetWord,
1112 NULL, &loadConf->globals.pszConfDAGFile, NULL));
1113 CHKiRet(regCfSysLineHdlr((uchar *)"umask", 0, eCmdHdlrFileCreateMode,
1114 NULL, &loadConf->globals.umask, NULL));
1115 CHKiRet(regCfSysLineHdlr((uchar *)"maxopenfiles", 0, eCmdHdlrInt,
1116 setMaxFiles, NULL, NULL));
1117
1118 CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt,
1119 setActionResumeInterval, NULL, NULL));
1120 CHKiRet(regCfSysLineHdlr((uchar *)"modload", 0, eCmdHdlrCustomHandler,
1121 conf.doModLoad, NULL, NULL));
1122 CHKiRet(regCfSysLineHdlr((uchar *)"defaultruleset", 0, eCmdHdlrGetWord,
1123 setDefaultRuleset, NULL, NULL));
1124 CHKiRet(regCfSysLineHdlr((uchar *)"ruleset", 0, eCmdHdlrGetWord,
1125 setCurrRuleset, NULL, NULL));
1126
1127 /* handler for "larger" config statements (tie into legacy conf system) */
1128 CHKiRet(regCfSysLineHdlr((uchar *)"template", 0, eCmdHdlrCustomHandler,
1129 conf.doNameLine, (void*)DIR_TEMPLATE, NULL));
1130 CHKiRet(regCfSysLineHdlr((uchar *)"outchannel", 0, eCmdHdlrCustomHandler,
1131 conf.doNameLine, (void*)DIR_OUTCHANNEL, NULL));
1132 CHKiRet(regCfSysLineHdlr((uchar *)"allowedsender", 0, eCmdHdlrCustomHandler,
1133 conf.doNameLine, (void*)DIR_ALLOWEDSENDER, NULL));
1134
1135 /* the following are parameters for the main message queue. I have the
1136 * strong feeling that this needs to go to a different space, but that
1137 * feeling may be wrong - we'll see how things evolve.
1138 * rgerhards, 2011-04-21
1139 */
1140 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuefilename", 0, eCmdHdlrGetWord,
1141 NULL, &loadConf->globals.mainQ.pszMainMsgQFName, NULL));
1142 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesize", 0, eCmdHdlrInt,
1143 NULL, &loadConf->globals.mainQ.iMainMsgQueueSize, NULL));
1144 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuehighwatermark", 0, eCmdHdlrInt,
1145 NULL, &loadConf->globals.mainQ.iMainMsgQHighWtrMark, NULL));
1146 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuelowwatermark", 0, eCmdHdlrInt,
1147 NULL, &loadConf->globals.mainQ.iMainMsgQLowWtrMark, NULL));
1148 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuediscardmark", 0, eCmdHdlrInt,
1149 NULL, &loadConf->globals.mainQ.iMainMsgQDiscardMark, NULL));
1150 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuediscardseverity", 0, eCmdHdlrSeverity,
1151 NULL, &loadConf->globals.mainQ.iMainMsgQDiscardSeverity, NULL));
1152 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuecheckpointinterval", 0, eCmdHdlrInt,
1153 NULL, &loadConf->globals.mainQ.iMainMsgQPersistUpdCnt, NULL));
1154 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesyncqueuefiles", 0, eCmdHdlrBinary,
1155 NULL, &loadConf->globals.mainQ.bMainMsgQSyncQeueFiles, NULL));
1156 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetype", 0, eCmdHdlrGetWord,
1157 setMainMsgQueType, NULL, NULL));
1158 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkerthreads", 0, eCmdHdlrInt,
1159 NULL, &loadConf->globals.mainQ.iMainMsgQueueNumWorkers, NULL));
1160 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutshutdown", 0, eCmdHdlrInt,
1161 NULL, &loadConf->globals.mainQ.iMainMsgQtoQShutdown, NULL));
1162 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutactioncompletion", 0, eCmdHdlrInt,
1163 NULL, &loadConf->globals.mainQ.iMainMsgQtoActShutdown, NULL));
1164 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutenqueue", 0, eCmdHdlrInt,
1165 NULL, &loadConf->globals.mainQ.iMainMsgQtoEnq, NULL));
1166 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkertimeoutthreadshutdown", 0, eCmdHdlrInt,
1167 NULL, &loadConf->globals.mainQ.iMainMsgQtoWrkShutdown, NULL));
1168 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeueslowdown", 0, eCmdHdlrInt,
1169 NULL, &loadConf->globals.mainQ.iMainMsgQDeqSlowdown, NULL));
1170 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkerthreadminimummessages", 0, eCmdHdlrInt,
1171 NULL, &loadConf->globals.mainQ.iMainMsgQWrkMinMsgs, NULL));
1172 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxfilesize", 0, eCmdHdlrSize,
1173 NULL, &loadConf->globals.mainQ.iMainMsgQueMaxFileSize, NULL));
1174 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuebatchsize", 0, eCmdHdlrSize,
1175 NULL, &loadConf->globals.mainQ.iMainMsgQueDeqBatchSize, NULL));
1176 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxdiskspace", 0, eCmdHdlrSize,
1177 NULL, &loadConf->globals.mainQ.iMainMsgQueMaxDiskSpace, NULL));
1178 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesaveonshutdown", 0, eCmdHdlrBinary,
1179 NULL, &loadConf->globals.mainQ.bMainMsgQSaveOnShutdown, NULL));
1180 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimebegin", 0, eCmdHdlrInt,
1181 NULL, &loadConf->globals.mainQ.iMainMsgQueueDeqtWinFromHr, NULL));
1182 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimeend", 0, eCmdHdlrInt,
1183 NULL, &loadConf->globals.mainQ.iMainMsgQueueDeqtWinToHr, NULL));
1184 /* moddir is a bit hard problem -- because it actually needs to
1185 * modify a setting that is specific to module.c. The important point
1186 * is that this action MUST actually be carried out during config load,
1187 * because we must load modules in order to get their config extensions
1188 * (no way around).
1189 * TODO: think about a clean solution
1190 */
1191 CHKiRet(regCfSysLineHdlr((uchar *)"moddir", 0, eCmdHdlrGetWord,
1192 setModDir, NULL, NULL));
1193
1194 /* finally, the reset handler */
1195 CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
1196 resetConfigVariables, NULL, NULL));
1197
1198 /* initialize the build-in templates */
1199 pTmp = template_DebugFormat;
1200 tplAddLine(ourConf, "RSYSLOG_DebugFormat", &pTmp);
1201 pTmp = template_SyslogProtocol23Format;
1202 tplAddLine(ourConf, "RSYSLOG_SyslogProtocol23Format", &pTmp);
1203 pTmp = template_FileFormat; /* new format for files with high-precision stamp */
1204 tplAddLine(ourConf, "RSYSLOG_FileFormat", &pTmp);
1205 pTmp = template_TraditionalFileFormat;
1206 tplAddLine(ourConf, "RSYSLOG_TraditionalFileFormat", &pTmp);
1207 pTmp = template_WallFmt;
1208 tplAddLine(ourConf, " WallFmt", &pTmp);
1209 pTmp = template_ForwardFormat;
1210 tplAddLine(ourConf, "RSYSLOG_ForwardFormat", &pTmp);
1211 pTmp = template_TraditionalForwardFormat;
1212 tplAddLine(ourConf, "RSYSLOG_TraditionalForwardFormat", &pTmp);
1213 pTmp = template_StdUsrMsgFmt;
1214 tplAddLine(ourConf, " StdUsrMsgFmt", &pTmp);
1215 pTmp = template_StdDBFmt;
1216 tplAddLine(ourConf, " StdDBFmt", &pTmp);
1217 pTmp = template_SysklogdFileFormat;
1218 tplAddLine(ourConf, "RSYSLOG_SysklogdFileFormat", &pTmp);
1219 pTmp = template_StdPgSQLFmt;
1220 tplAddLine(ourConf, " StdPgSQLFmt", &pTmp);
1221 pTmp = template_StdJSONFmt;
1222 tplAddLine(ourConf, " StdJSONFmt", &pTmp);
1223 pTmp = template_spoofadr;
1224 tplLastStaticInit(ourConf, tplAddLine(ourConf, "RSYSLOG_omudpspoofDfltSourceTpl", &pTmp));
1225
1226finalize_it:
1227 RETiRet;
1228}
1229
1230
1231/* validate the current configuration, generate error messages, do
1232 * optimizations, etc, etc,...
1233 */
1234static inline rsRetVal
1235validateConf(void)
1236{
1237 DEFiRet;
1238
1239 /* some checks */
1240 if(ourConf->globals.mainQ.iMainMsgQueueNumWorkers < 1) {
1241 errmsg.LogError(0, NO_ERRCODE, "$MainMsgQueueNumWorkers must be at least 1! Set to 1.\n");
1242 ourConf->globals.mainQ.iMainMsgQueueNumWorkers = 1;
1243 }
1244
1245 if(ourConf->globals.mainQ.MainMsgQueType == QUEUETYPE_DISK) {
1246 errno = 0; /* for logerror! */
1247 if(glbl.GetWorkDir() == NULL) {
1248 errmsg.LogError(0, NO_ERRCODE, "No $WorkDirectory specified - can not run main message queue in 'disk' mode. "
1249 "Using 'FixedArray' instead.\n");
1250 ourConf->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
1251 }
1252 if(ourConf->globals.mainQ.pszMainMsgQFName == NULL) {
1253 errmsg.LogError(0, NO_ERRCODE, "No $MainMsgQueueFileName specified - can not run main message queue in "
1254 "'disk' mode. Using 'FixedArray' instead.\n");
1255 ourConf->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
1256 }
1257 }
1258 RETiRet;
1259}
1260
1261
1262/* Load a configuration. This will do all necessary steps to create
1263 * the in-memory representation of the configuration, including support
1264 * for multiple configuration languages.
1265 * Note that to support the legacy language we must provide some global
1266 * object that holds the currently-being-loaded config ptr.
1267 * Begun 2011-04-20, rgerhards
1268 */
1269rsRetVal
1270load(rsconf_t **cnf, uchar *confFile)
1271{
1272 int iNbrActions;
1273 int r;
1274 DEFiRet;
1275
1276 CHKiRet(rsconfConstruct(&loadConf));
1277ourConf = loadConf; // TODO: remove, once ourConf is gone!
1278
1279 CHKiRet(loadBuildInModules());
1280 CHKiRet(initLegacyConf());
1281
1282 /* open the configuration file */
1283 r = cnfSetLexFile((char*)confFile);
1284 if(r == 0) {
1285 r = yyparse();
1286 conf.GetNbrActActions(loadConf, &iNbrActions);
1287 }
1288
1289 if(r == 1) {
1290 errmsg.LogError(0, RS_RET_CONF_PARSE_ERROR,
1291 "CONFIG ERROR: could not interpret master "
1292 "config file '%s'.", confFile);
1293 ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR);
1294 } else if(iNbrActions == 0) {
1295 errmsg.LogError(0, RS_RET_NO_ACTIONS, "CONFIG ERROR: there are no "
1296 "active actions configured. Inputs will "
1297 "run, but no output whatsoever is created.");
1298 ABORT_FINALIZE(RS_RET_NO_ACTIONS);
1299 }
1300 tellLexEndParsing();
1301 rulesetOptimizeAll(loadConf);
1302
1303 tellCoreConfigLoadDone();
1304 tellModulesConfigLoadDone();
1305
1306 tellModulesCheckConfig();
1307 CHKiRet(validateConf());
1308
1309 /* we are done checking the config - now validate if we should actually run or not.
1310 * If not, terminate. -- rgerhards, 2008-07-25
1311 * TODO: iConfigVerify -- should it be pulled from the config, or leave as is (option)?
1312 */
1313 if(iConfigVerify) {
1314 if(iRet == RS_RET_OK)
1315 iRet = RS_RET_VALIDATION_RUN;
1316 FINALIZE;
1317 }
1318
1319 /* all OK, pass loaded conf to caller */
1320 *cnf = loadConf;
1321// TODO: enable this once all config code is moved to here! loadConf = NULL;
1322
1323 dbgprintf("rsyslog finished loading master config %p\n", loadConf);
1324 rsconfDebugPrint(loadConf);
1325
1326finalize_it:
1327 RETiRet;
1328}
1329
1330
1331/* queryInterface function
1332 */
1333BEGINobjQueryInterface(rsconf)
1334CODESTARTobjQueryInterface(rsconf)
1335 if(pIf->ifVersion != rsconfCURR_IF_VERSION) { /* check for current version, increment on each change */
1336 ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
1337 }
1338
1339 /* ok, we have the right interface, so let's fill it
1340 * Please note that we may also do some backwards-compatibility
1341 * work here (if we can support an older interface version - that,
1342 * of course, also affects the "if" above).
1343 */
1344 pIf->Construct = rsconfConstruct;
1345 pIf->ConstructFinalize = rsconfConstructFinalize;
1346 pIf->Destruct = rsconfDestruct;
1347 pIf->DebugPrint = rsconfDebugPrint;
1348 pIf->Load = load;
1349 pIf->Activate = activate;
1350finalize_it:
1351ENDobjQueryInterface(rsconf)
1352
1353
1354/* Initialize the rsconf class. Must be called as the very first method
1355 * before anything else is called inside this class.
1356 */
1357BEGINObjClassInit(rsconf, 1, OBJ_IS_CORE_MODULE) /* class, version */
1358 /* request objects we use */
1359 CHKiRet(objUse(ruleset, CORE_COMPONENT));
1360 CHKiRet(objUse(module, CORE_COMPONENT));
1361 CHKiRet(objUse(conf, CORE_COMPONENT));
1362 CHKiRet(objUse(errmsg, CORE_COMPONENT));
1363 CHKiRet(objUse(glbl, CORE_COMPONENT));
1364 CHKiRet(objUse(datetime, CORE_COMPONENT));
1365 CHKiRet(objUse(parser, CORE_COMPONENT));
1366
1367 /* now set our own handlers */
1368 OBJSetMethodHandler(objMethod_DEBUGPRINT, rsconfDebugPrint);
1369 OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, rsconfConstructFinalize);
1370ENDObjClassInit(rsconf)
1371
1372
1373/* De-initialize the rsconf class.
1374 */
1375BEGINObjClassExit(rsconf, OBJ_IS_CORE_MODULE) /* class, version */
1376 objRelease(ruleset, CORE_COMPONENT);
1377 objRelease(module, CORE_COMPONENT);
1378 objRelease(conf, CORE_COMPONENT);
1379 objRelease(errmsg, CORE_COMPONENT);
1380 objRelease(glbl, CORE_COMPONENT);
1381 objRelease(datetime, CORE_COMPONENT);
1382 objRelease(parser, CORE_COMPONENT);
1383ENDObjClassExit(rsconf)
1384
1385/* vi:set ai:
1386 */
01387
=== modified file '.pc/applied-patches'
--- .pc/applied-patches 2013-10-21 15:31:38 +0000
+++ .pc/applied-patches 2013-12-04 13:07:52 +0000
@@ -1,1 +1,2 @@
101-dont_create_db.patch101-dont_create_db.patch
210-initgroups.patch
23
=== modified file 'debian/changelog'
--- debian/changelog 2013-10-21 15:31:38 +0000
+++ debian/changelog 2013-12-04 13:07:52 +0000
@@ -1,3 +1,15 @@
1rsyslog (7.4.4-1ubuntu2) UNRELEASED; urgency=low
2
3 * debian/rsyslog.postinst: Make sure /var/log is owned by group syslog and
4 is group-writeable (LP: #1256695).
5 * Ensure that rsyslogd can create files in group adm, even when dropping
6 group privileges to syslog (LP: #484336):
7 - debian/patches/10-initgroups.patch: Try to set appropriate
8 supplementary groups before dropping UID.
9 - debian/rsyslog.postinst: Add syslog user to group adm.
10
11 -- Colin Watson <cjwatson@ubuntu.com> Wed, 04 Dec 2013 11:46:11 +0000
12
1rsyslog (7.4.4-1ubuntu1) trusty; urgency=low13rsyslog (7.4.4-1ubuntu1) trusty; urgency=low
214
3 * Merge from Debian unstable, remaining changes:15 * Merge from Debian unstable, remaining changes:
416
=== added file 'debian/patches/10-initgroups.patch'
--- debian/patches/10-initgroups.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/10-initgroups.patch 2013-12-04 13:07:52 +0000
@@ -0,0 +1,44 @@
1Description: Try to set supplementary groups before dropping UID
2Author: Colin Watson <cjwatson@ubuntu.com>
3Bug-Ubuntu: https://bugs.launchpad.net/bugs/484336
4Bug-Ubuntu: https://bugs.launchpad.net/bugs/1256695
5Bug-Ubuntu: https://bugs.launchpad.net/bugs/1257633
6Forwarded: no
7Last-Update: 2013-12-04
8
9Index: b/runtime/rsconf.c
10===================================================================
11--- a/runtime/rsconf.c
12+++ b/runtime/rsconf.c
13@@ -27,6 +27,7 @@
14 #include <string.h>
15 #include <errno.h>
16 #include <unistd.h>
17+#include <pwd.h>
18 #include <grp.h>
19 #include <stdarg.h>
20 #include <sys/resource.h>
21@@ -533,6 +534,23 @@
22 {
23 int res;
24 uchar szBuf[1024];
25+ struct passwd *pw;
26+ gid_t gid;
27+
28+ /* Try to set appropriate supplementary groups for this user.
29+ * Failure is not fatal.
30+ */
31+ pw = getpwuid(iUid);
32+ if (pw) {
33+ gid = getgid();
34+ res = initgroups(pw->pw_name, gid);
35+ DBGPRINTF("initgroups(%s, %d): %d\n", pw->pw_name, gid, res);
36+ } else {
37+ rs_strerror_r(errno, szBuf, sizeof(szBuf));
38+ errmsg.LogError(0, NO_ERRCODE,
39+ "could not get username for userid %d: %s",
40+ iUid, szBuf);
41+ }
42
43 res = setuid(iUid);
44 if(res) {
045
=== modified file 'debian/patches/series'
--- debian/patches/series 2013-10-21 15:31:38 +0000
+++ debian/patches/series 2013-12-04 13:07:52 +0000
@@ -1,2 +1,3 @@
1# Debian patches for rsyslog1# Debian patches for rsyslog
201-dont_create_db.patch201-dont_create_db.patch
310-initgroups.patch
34
=== modified file 'debian/rsyslog.postinst'
--- debian/rsyslog.postinst 2013-10-21 15:31:38 +0000
+++ debian/rsyslog.postinst 2013-12-04 13:07:52 +0000
@@ -24,10 +24,16 @@
24 ucfr rsyslog $user_conf24 ucfr rsyslog $user_conf
2525
26 adduser --system --group --no-create-home --quiet syslog || true26 adduser --system --group --no-create-home --quiet syslog || true
27 adduser syslog adm || true
2728
28 # fix ownership of work directory (LP: #1075901)29 # fix ownership of work directory (LP: #1075901)
29 chown syslog:adm /var/spool/rsyslog30 chown syslog:adm /var/spool/rsyslog
3031
32 # ensure that rsyslogd can create log files after dropping
33 # privileges
34 chgrp syslog /var/log
35 chmod g+w /var/log
36
31 # /run transition (Bug: #633036)37 # /run transition (Bug: #633036)
32 if dpkg --compare-versions "$2" lt "5.8.2-2"; then38 if dpkg --compare-versions "$2" lt "5.8.2-2"; then
33 rm -f /lib/init/rw/sendsigs.omit.d/rsyslog39 rm -f /lib/init/rw/sendsigs.omit.d/rsyslog
3440
=== modified file 'runtime/rsconf.c'
--- runtime/rsconf.c 2013-03-18 16:21:35 +0000
+++ runtime/rsconf.c 2013-12-04 13:07:52 +0000
@@ -27,6 +27,7 @@
27#include <string.h>27#include <string.h>
28#include <errno.h>28#include <errno.h>
29#include <unistd.h>29#include <unistd.h>
30#include <pwd.h>
30#include <grp.h>31#include <grp.h>
31#include <stdarg.h>32#include <stdarg.h>
32#include <sys/resource.h>33#include <sys/resource.h>
@@ -533,6 +534,23 @@
533{534{
534 int res;535 int res;
535 uchar szBuf[1024];536 uchar szBuf[1024];
537 struct passwd *pw;
538 gid_t gid;
539
540 /* Try to set appropriate supplementary groups for this user.
541 * Failure is not fatal.
542 */
543 pw = getpwuid(iUid);
544 if (pw) {
545 gid = getgid();
546 res = initgroups(pw->pw_name, gid);
547 DBGPRINTF("initgroups(%s, %d): %d\n", pw->pw_name, gid, res);
548 } else {
549 rs_strerror_r(errno, szBuf, sizeof(szBuf));
550 errmsg.LogError(0, NO_ERRCODE,
551 "could not get username for userid %d: %s",
552 iUid, szBuf);
553 }
536554
537 res = setuid(iUid);555 res = setuid(iUid);
538 if(res) {556 if(res) {

Subscribers

People subscribed via source and target branches

to all changes: